00001 #define DEBUG 0
00002
00003
00004
00005
00006
00007
00008
00009
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 #include "jsoc_main.h"
00088 #include "drms.h"
00089 #include "drms_names.h"
00090 #include "json.h"
00091 #include <time.h>
00092 #include <sys/types.h>
00093 #include <unistd.h>
00094 #include "printk.h"
00095 #include "exputil.h"
00096 #include "qDecoder.h"
00097 #include "fitsexport.h"
00098
00099 char *MISSING_KEY_NAME = "???";
00100 char *MISSING_KEY_VALUE = "???";
00101 char *MISSING_SEG_NAME = "???";
00102 char *MISSING_LINK_NAME = "???";
00103 char *INVALID = "invalid";
00104
00105 #define USE_FITS_NAMES_FOR_COLUMNS (0)
00106
00107 char invalidObj;
00108 const char *userhandle = NULL;
00109
00110 #define JSONDIE(msg) \
00111 do { \
00112 char *msgjson; \
00113 char *json; \
00114 json_t *jroot = json_new_object(); \
00115 msgjson = string_to_json(msg); \
00116 json_insert_pair_into_object(jroot, "status", json_new_number("1")); \
00117 json_insert_pair_into_object(jroot, "error", json_new_string(msgjson)); \
00118 json_tree_to_string(jroot,&json); \
00119 printf("Content-type: application/json\n\n"); \
00120 printf("%s\n",json); \
00121 free(json); \
00122 fflush(stdout); \
00123 manage_userhandle(0, userhandle); \
00124 return(1); \
00125 } while(0)
00126
00127 #ifndef NDEBUG
00128 #define JSOC_INFO_ASSERT(expression, msg) XASSERT(expression)
00129 #else
00130 #define JSOC_INFO_ASSERT(expression, msg) \
00131 do { \
00132 if (!(expression)) \
00133 { \
00134 JSONDIE(msg); \
00135 } \
00136 } while(0)
00137 #endif
00138
00139 struct requisitionStructT
00140 {
00141 unsigned int requireRecnum : 1;
00142 unsigned int requireSunum : 1;
00143 unsigned int requireSUMinfoSize : 1;
00144 unsigned int requireSUMinfoOnline : 1;
00145 unsigned int requireSUMinfoRetain : 1;
00146 unsigned int requireSUMinfoArchive : 1;
00147 unsigned int requireRecdir : 1;
00148 unsigned int requireDirmtime : 1;
00149 unsigned int requireLogdir : 1;
00150 unsigned int requireSUMinfo : 1;
00151 };
00152
00153 static int isInvalidKey(DRMS_Keyword_t *key)
00154 {
00155 if (key)
00156 {
00157 return (void *)(key->record) == (void *)(&invalidObj);
00158 }
00159
00160 return 1;
00161 }
00162
00163 static int isInvalidSeg(DRMS_Segment_t *seg)
00164 {
00165 if (seg)
00166 {
00167 return (void *)(seg->record) == (void *)(&invalidObj);
00168 }
00169
00170 return 1;
00171 }
00172
00173 static int isInvalidLink(DRMS_Link_t *link)
00174 {
00175 if (link)
00176 {
00177 return (void *)(link->record) == (void *)(&invalidObj);
00178 }
00179
00180 return 1;
00181 }
00182
00183 static char *string_to_json(char *in)
00184 {
00185 char *new;
00186 new = json_escape(in);
00187 return(new);
00188 }
00189
00190 void manage_userhandle(int register_handle, const char *handle)
00191 {
00192 char cmd[1024];
00193
00194 if (register_handle)
00195 {
00196 long PID = getpid();
00197 exputl_manage_cgibin_handles("a", handle, PID, NULL);
00198 }
00199 else if (handle && *handle)
00200 {
00201 exputl_manage_cgibin_handles("d", handle, -1, NULL);
00202 }
00203 }
00204
00205 static int populateKeyList(const char *listOfKeys, LinkedList_t *reqSegs, DRMS_Record_t *template, DRMS_Record_t **jsdTemplate, DRMS_RecordSet_t *recordSet, int *recsStaged, struct requisitionStructT *requisition, LinkedList_t *reqKeys)
00206 {
00207 char *listOfKeysWorking = NULL;
00208 char *currentKey = NULL;
00209 char *saver = NULL;
00210 HIterator_t *last = NULL;
00211 DRMS_Keyword_t *keyTemplate = NULL;
00212 int status = DRMS_SUCCESS;
00213 int sumInfoSizeKey = 0;
00214 int sumInfoOnlineKey = 0;
00215 int sumInfoRetainKey = 0;
00216 int sumInfoArchiveKey = 0;
00217 int recnumKey = 0;
00218 int sunumKey = 0;
00219 int recdirKey = 0;
00220 int dirmtimeKey = 0;
00221 int logdirKey = 0;
00222 int sumInfoFakeKey = 0;
00223 int fakeKey = 0;
00224
00225 JSOC_INFO_ASSERT(listOfKeys && *listOfKeys != '\0' && reqSegs && template && jsdTemplate && recordSet && recsStaged && requisition && reqKeys, "populateKeyList(): invalid arguments");
00226 listOfKeysWorking = strdup(listOfKeys);
00227 JSOC_INFO_ASSERT(listOfKeysWorking, "populateKeyList(): out of memory");
00228
00229
00230
00231 for (currentKey = strtok_r(listOfKeysWorking, ",", &saver); currentKey; currentKey=strtok_r(NULL, ",", &saver))
00232 {
00233 if ((strcmp(currentKey,"**NONE**") == 0))
00234 {
00235 JSOC_INFO_ASSERT(list_llgetnitems(reqKeys) == 0, "Invalid key list (cannot specify **NONE** with other keys).");
00236 }
00237 else if ((strcmp(currentKey, "**ALL**") == 0))
00238 {
00239
00240
00241
00242
00243 if (!*jsdTemplate)
00244 {
00245 *jsdTemplate = drms_create_jsdtemplate_record(drms_env, template->seriesinfo->seriesname, &status);
00246 }
00247
00248 JSOC_INFO_ASSERT(*jsdTemplate, "Could not obtain the JSD template record.");
00249 JSOC_INFO_ASSERT(last == NULL, "");
00250
00251 while ((keyTemplate = drms_record_nextkey(*jsdTemplate, &last, 0)) != NULL)
00252 {
00253 JSOC_INFO_ASSERT(keyTemplate->info && *(keyTemplate->info->name) != '\0', "Invalid keyword information.");
00254
00255 if (!drms_keyword_getimplicit(keyTemplate))
00256 {
00257 if (drms_keyword_getperseg(keyTemplate))
00258 {
00259
00260
00261
00262 if (list_llgetnitems(reqSegs) > 0)
00263 {
00264 if (!list_llfind(reqKeys, (void *)&keyTemplate))
00265 {
00266
00267 list_llinserttail(reqKeys, (void *)&keyTemplate);
00268 }
00269 }
00270 }
00271 else
00272 {
00273 if (!list_llfind(reqKeys, (void *)&keyTemplate))
00274 {
00275
00276 list_llinserttail(reqKeys, (void *)&keyTemplate);
00277 }
00278 }
00279 }
00280 }
00281
00282 if (last)
00283 {
00284 hiter_destroy(&last);
00285 }
00286 }
00287 else
00288 {
00289
00290 if ((recnumKey = (strcasecmp(currentKey, "*recnum*") == 0)) && !requisition->requireRecnum)
00291 {
00292 requisition->requireRecnum = 1;
00293 }
00294
00295 if ((sunumKey = (strcasecmp(currentKey, "*sunum*") == 0)) && !requisition->requireSunum)
00296 {
00297 requisition->requireSunum = 1;
00298 }
00299
00300 if ((sumInfoSizeKey = (strcasecmp(currentKey, "*size*") == 0)) && !requisition->requireSUMinfoSize)
00301 {
00302 requisition->requireSUMinfoSize = 1;
00303 }
00304
00305 if ((sumInfoOnlineKey = (strcasecmp(currentKey, "*online*") == 0)) && !requisition->requireSUMinfoOnline)
00306 {
00307 requisition->requireSUMinfoOnline = 1;
00308 }
00309
00310 if ((sumInfoRetainKey = (strcasecmp(currentKey, "*retain*") == 0)) && !requisition->requireSUMinfoRetain)
00311 {
00312 requisition->requireSUMinfoRetain = 1;
00313 }
00314
00315 if ((sumInfoArchiveKey = (strcasecmp(currentKey, "*archive*") == 0)) && !requisition->requireSUMinfoArchive)
00316 {
00317 requisition->requireSUMinfoArchive = 1;
00318 }
00319
00320 if ((recdirKey = (strcasecmp(currentKey, "*recdir*") == 0)) && !requisition->requireRecdir)
00321 {
00322 requisition->requireRecdir = 1;
00323
00324 if (!*recsStaged)
00325 {
00326 drms_stage_records(recordSet, 0, 0);
00327 *recsStaged = 1;
00328 }
00329 }
00330
00331 if ((dirmtimeKey = (strcasecmp(currentKey, "*dirmtime*") == 0)) && !requisition->requireDirmtime)
00332 {
00333 requisition->requireDirmtime = 1;
00334
00335 if (!*recsStaged)
00336 {
00337 drms_stage_records(recordSet, 0, 0);
00338 *recsStaged = 1;
00339 }
00340 }
00341
00342 if ((logdirKey = (strcasecmp(currentKey, "*logdir*") == 0)) && !requisition->requireLogdir)
00343 {
00344 requisition->requireLogdir = 1;
00345 }
00346
00347 sumInfoFakeKey = sumInfoSizeKey | sumInfoOnlineKey | sumInfoRetainKey | sumInfoArchiveKey;
00348 fakeKey = sumInfoFakeKey | recnumKey | sunumKey | recdirKey | dirmtimeKey | logdirKey;
00349
00350 if (!requisition->requireSUMinfo)
00351 {
00352 requisition->requireSUMinfo = sumInfoFakeKey;
00353 }
00354
00355
00356
00357 if (!fakeKey)
00358 {
00359 if (!*jsdTemplate)
00360 {
00361 *jsdTemplate = drms_create_jsdtemplate_record(drms_env, template->seriesinfo->seriesname, &status);
00362 }
00363
00364 JSOC_INFO_ASSERT(*jsdTemplate, "Could not obtain the JSD template record.");
00365
00366
00367 keyTemplate = drms_keyword_lookup(*jsdTemplate, currentKey, 0);
00368
00369 if (!keyTemplate || !(keyTemplate->info) || *(keyTemplate->info->name) == '\0')
00370 {
00371 keyTemplate = calloc(1, sizeof(DRMS_Keyword_t));
00372 keyTemplate->record = (DRMS_Record_t *)(&invalidObj);
00373 keyTemplate->info = (DRMS_KeywordInfo_t *)(strdup(currentKey));
00374 }
00375 else if (drms_keyword_getimplicit(keyTemplate))
00376 {
00377 keyTemplate = calloc(1, sizeof(DRMS_Keyword_t));
00378 keyTemplate->record = (DRMS_Record_t *)(&invalidObj);
00379 keyTemplate->info = (DRMS_KeywordInfo_t *)(strdup(currentKey));
00380 }
00381
00382 if (!list_llfind(reqKeys, (void *)&keyTemplate))
00383 {
00384
00385 list_llinserttail(reqKeys, (void *)&keyTemplate);
00386 }
00387 }
00388 }
00389 }
00390
00391 free(listOfKeysWorking);
00392
00393 return list_llgetnitems(reqKeys);
00394 }
00395
00396 static int populateSegList(const char *listOfSegs, int followLinks, DRMS_Record_t *template, DRMS_RecordSet_t *recordSet, int *recsStaged, struct requisitionStructT *requisition, LinkedList_t *reqSegs)
00397 {
00398 char *listOfSegsWorking = NULL;
00399 char *currentSeg = NULL;
00400 char *saver = NULL;
00401 HIterator_t *last = NULL;
00402 DRMS_Segment_t *segTemplate = NULL;
00403
00404 JSOC_INFO_ASSERT(listOfSegs && *listOfSegs != '\0' && template && recordSet && recsStaged && requisition && reqSegs, "populateSegList(): invalid arguments");
00405
00406 listOfSegsWorking = strdup(listOfSegs);
00407 JSOC_INFO_ASSERT(listOfSegsWorking, "populateSegList(): out of memory");
00408
00409 for (currentSeg = strtok_r(listOfSegsWorking, ",", &saver); currentSeg; currentSeg = strtok_r(NULL, ",", &saver))
00410 {
00411 if (strcmp(currentSeg, "**NONE**") == 0)
00412 {
00413 JSOC_INFO_ASSERT(list_llgetnitems(reqSegs) == 0, "Invalid segment list (cannot specify **NONE** with other segments).");
00414 }
00415 else if ((strcmp(currentSeg, "**ALL**") == 0))
00416 {
00417 JSOC_INFO_ASSERT(last == NULL, "about to leak");
00418
00419 while ((segTemplate = drms_record_nextseg(template, &last, 0)) != NULL)
00420 {
00421 JSOC_INFO_ASSERT(segTemplate && segTemplate->info && *(segTemplate->info->name) != '\0', "Invalid segment information.");
00422
00423 if (followLinks && segTemplate->info->islink)
00424 {
00425
00426
00427 int lnkstat = DRMS_SUCCESS;
00428
00429 drms_template_segment_followlink(segTemplate, &lnkstat);
00430 JSOC_INFO_ASSERT(lnkstat != DRMS_SUCCESS, "Unable to follow link.");
00431 }
00432
00433 if (!list_llfind(reqSegs, (void *)&segTemplate))
00434 {
00435
00436 list_llinserttail(reqSegs, (void *)&segTemplate);
00437 }
00438 }
00439
00440 if (last)
00441 {
00442 hiter_destroy(&last);
00443 }
00444 }
00445 else
00446 {
00447
00448 segTemplate = hcon_lookup_lower(&(template->segments), currentSeg);
00449
00450 if (!segTemplate || !(segTemplate->info) || *(segTemplate->info->name) == '\0')
00451 {
00452 segTemplate = calloc(1, sizeof(DRMS_Segment_t));
00453 segTemplate->record = (DRMS_Record_t *)(&invalidObj);
00454 segTemplate->info = (DRMS_SegmentInfo_t *)strdup(currentSeg);
00455 }
00456 else
00457 {
00458 if (followLinks && segTemplate->info->islink)
00459 {
00460
00461
00462
00463 int lnkstat = DRMS_SUCCESS;
00464
00465 drms_template_segment_followlink(segTemplate, &lnkstat);
00466 if (lnkstat != DRMS_SUCCESS)
00467 {
00468 segTemplate = calloc(1, sizeof(DRMS_Segment_t));
00469 segTemplate->record = (DRMS_Record_t *)(&invalidObj);
00470 segTemplate->info = (DRMS_SegmentInfo_t *)(strdup(currentSeg));
00471 }
00472 }
00473 }
00474
00475 if (!list_llfind(reqSegs, (void *)&segTemplate))
00476 {
00477
00478 list_llinserttail(reqSegs, (void *)&segTemplate);
00479 }
00480 }
00481 }
00482
00483 if (list_llgetnitems(reqSegs) > 0)
00484 {
00485 if (!*recsStaged)
00486 {
00487 drms_stage_records(recordSet, 0, 0);
00488 *recsStaged = 1;
00489 }
00490
00491 if (!requisition->requireSUMinfo)
00492 {
00493
00494 requisition->requireSUMinfo = 1;
00495 }
00496 }
00497
00498 return list_llgetnitems(reqSegs);
00499 }
00500
00501 static int populateLinkList(const char *listOfLinks, DRMS_Record_t *template, LinkedList_t *reqLinks)
00502 {
00503 char *listOfLinksWorking = NULL;
00504 char *currentLink = NULL;
00505 char *saver = NULL;
00506 HIterator_t *last = NULL;
00507 DRMS_Link_t *linkTemplate = NULL;
00508
00509 JSOC_INFO_ASSERT(listOfLinks && *listOfLinks != '\0' && template && reqLinks, "populateLinkList(): invalid arguments");
00510
00511 listOfLinksWorking = strdup(listOfLinks);
00512 JSOC_INFO_ASSERT(listOfLinksWorking, "populateLinkList(): out of memory");
00513
00514 for (currentLink = strtok_r(listOfLinksWorking, ",", &saver); currentLink != NULL; currentLink = strtok_r(NULL, ",", &saver))
00515 {
00516 if (strcmp(currentLink, "**NONE**") == 0)
00517 {
00518 JSOC_INFO_ASSERT(list_llgetnitems(reqLinks) == 0, "Invalid link list (cannot specify **NONE** with other links).");
00519 }
00520 else if (strcmp(currentLink, "**ALL**")==0)
00521 {
00522 DRMS_Link_t *link = NULL;
00523
00524 JSOC_INFO_ASSERT(last == NULL, "about to leak");
00525 while ((linkTemplate = drms_record_nextlink(template, &last)) != NULL)
00526 {
00527 JSOC_INFO_ASSERT(linkTemplate->info && *(linkTemplate->info->name) != '\0', "Invalid link information.");
00528 if (!list_llfind(reqLinks, (void *)&linkTemplate))
00529 {
00530 list_llinserttail(reqLinks, (void *)&linkTemplate);
00531 }
00532 }
00533
00534 if (last)
00535 {
00536 hiter_destroy(&last);
00537 }
00538 }
00539 else
00540 {
00541 linkTemplate = hcon_lookup_lower(&template->links, currentLink);
00542
00543 if (!linkTemplate || !(linkTemplate->info) || *(linkTemplate->info->name) == '\0')
00544 {
00545 linkTemplate = calloc(1, sizeof(DRMS_Link_t));
00546 linkTemplate->record = (DRMS_Record_t *)(&invalidObj);
00547 linkTemplate->info = (DRMS_LinkInfo_t *)(strdup(currentLink));
00548 }
00549
00550 if (!list_llfind(reqLinks, (void *)&linkTemplate))
00551 {
00552 list_llinserttail(reqLinks, (void *)&linkTemplate);
00553 }
00554 }
00555 }
00556
00557 return list_llgetnitems(reqLinks);
00558 }
00559
00560 static char x2c (char *what)
00561 {
00562 char digit;
00563 digit = (char)(what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
00564 digit *= 16;
00565 digit = (char)(digit + (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')));
00566 return (digit);
00567 }
00568
00569 static void CGI_unescape_url (char *url)
00570 {
00571 int x, y;
00572 for (x = 0, y = 0; url[y]; ++x, ++y)
00573 {
00574 if ((url[x] = url[y]) == '%')
00575 {
00576 url[x] = x2c (&url[y+1]);
00577 y += 2;
00578 }
00579 }
00580 url[x] = '\0';
00581 }
00582
00583
00584
00585
00586
00587
00588
00589 char *drms_record_getlogdir(DRMS_Record_t *rec)
00590 {
00591 char *logpath;
00592 char query[DRMS_MAXQUERYLEN];
00593 DB_Text_Result_t *qres;
00594
00595 sprintf(query, "select sunum from %s.drms_session where sessionid=%lld", rec->sessionns, rec->sessionid);
00596 if ((qres = drms_query_txt(drms_env->session, query)) && qres->num_rows>0)
00597 {
00598 if (qres->field[0][0][0] == '\0')
00599 logpath = strdup("No log avaliable");
00600 else
00601 {
00602 DRMS_StorageUnit_t *su;
00603 int status, save_retention = drms_env->retention;
00604 int retrieve = 0;
00605 su = malloc(sizeof(DRMS_StorageUnit_t));
00606 su->sunum = atoll(qres->field[0][0]);
00607 drms_env->retention = DRMS_LOG_RETENTION;
00608 status = drms_su_getsudir(drms_env, su, retrieve);
00609 if (!status)
00610 logpath = strdup(su->sudir);
00611 else
00612 logpath = strdup("Log offline");
00613 free(su);
00614 drms_env->retention = save_retention;
00615 }
00616 }
00617 else
00618 logpath = strdup("Log query failed");
00619 db_free_text_result(qres);
00620 return logpath;
00621 }
00622
00623 int drms_ismissing_keyval(DRMS_Keyword_t *key)
00624 {
00625 XASSERT(key);
00626 switch(key->info->type)
00627 {
00628 case DRMS_TYPE_CHAR:
00629 return(drms_ismissing_char(key->value.char_val));
00630 case DRMS_TYPE_SHORT:
00631 return(drms_ismissing_short(key->value.short_val));
00632 case DRMS_TYPE_INT:
00633 return(drms_ismissing_int(key->value.int_val));
00634 case DRMS_TYPE_LONGLONG:
00635 return(drms_ismissing_longlong(key->value.longlong_val));
00636 case DRMS_TYPE_FLOAT:
00637 return(drms_ismissing_float(key->value.float_val));
00638 case DRMS_TYPE_DOUBLE:
00639 return(drms_ismissing_double(key->value.double_val));
00640 case DRMS_TYPE_TIME:
00641 return(drms_ismissing_time(key->value.time_val));
00642 case DRMS_TYPE_STRING:
00643 return(drms_ismissing_string(key->value.string_val));
00644 default:
00645 fprintf(stderr, "ERROR: Unhandled DRMS type %d\n",(int)key->info->type);
00646 XASSERT(0);
00647 }
00648 return 0;
00649 }
00650
00651
00652
00653
00654
00655
00656 ModuleArgs_t module_args[] =
00657 {
00658 {ARG_STRING, "op", "Not Specified", "<Operation>, values are: series_struct, rs_summary, or rs_list "},
00659 {ARG_STRING, "ds", "Not Specified", "<record_set query>"},
00660 {ARG_STRING, "key", "Not Specified", "<comma delimited keyword list>, keywords or special values: **ALL**, **NONE**, *recnum*, *sunum*, *size*, *online*, *retain*, *archive*, *logdir*, *dir_mtime* "},
00661 {ARG_STRING, "link", "Not Specified", "<comma delimited linkname list>, links or special values: **ALL**, **NONE**"},
00662 {ARG_STRING, "seg", "Not Specified", "<comma delimited segment list>, segnames or special values: **ALL**, **NONE** "},
00663 {ARG_STRING, "userhandle", "Not Specified", "Unique request identifier to allow possible user kill of this program."},
00664 {ARG_FLAG, "l", NULL, "Follow links to linked segments."},
00665 {ARG_INT, "n", "0", "RecordSet Limit"},
00666 {ARG_FLAG, "h", "0", "help - show usage"},
00667 {ARG_FLAG, "R", "0", "Show record query"},
00668 {ARG_FLAG, "z", "0", "emit JSON output"},
00669 {ARG_FLAG, "o", "0", "print additional DRMS information when op==series_struct"},
00670 {ARG_FLAG, "f", NULL, "print FITS keyword names, instead of DRMS keyword names"},
00671 {ARG_FLAG, "r", NULL, "do NOT display run time"},
00672 {ARG_STRING, "QUERY_STRING", "Not Specified", "AJAX query from the web"},
00673 {ARG_STRING, "REMOTE_ADDR", "0.0.0.0", "Remote IP address"},
00674 {ARG_STRING, "SERVER_NAME", "ServerName", "JSOC Server Name"},
00675 {ARG_END}
00676 };
00677
00678 char *module_name = "jsoc_info";
00680 int nice_intro ()
00681 {
00682 int usage = cmdparams_get_int (&cmdparams, "h", NULL);
00683 if (usage)
00684 {
00685 printf ("Usage:\njsoc_info {-h} {-z} {-R} "
00686 "op=<command> ds=<recordset query> {n=<rslimit>} {key=<keylist>} {seg=<segment_list>}\n"
00687 " details are:\n"
00688 "-h -> print this message\n"
00689 "-z -> emit json output, default at present.\n"
00690 "-R -> include record query.\n"
00691 "op=<command> tell which ajax function to execute, values are: series_struct, rs_summary, or rs_list \n"
00692 "ds=<recordset query> as <series>{[record specifier]} - required\n"
00693 "n=<rslimit> set optional record count limit, <0 from end, >0 from head\n"
00694 "key=<comma delimited keyword list>, keywords or special values: **ALL**, **NONE**, *recnum*, *sunum*, *size*, *online*, *retain*, *archive*, *logdir*, *dir_mtime* \n"
00695 "seg=<comma delimited segment list>, segnames or special values: **ALL**, **NONE** \n"
00696 "userhandle=<userhandle> unique id to allow user to kill this program by passing userhandle to jsoc_userkill.\n"
00697 "QUERY_STRING=<cgi-bin params>, parameter string as delivered from cgi-bin call.\n"
00698 );
00699 return(1);
00700 }
00701 return (0);
00702 }
00703
00704
00705 DRMS_RecordSet_t *drms_find_rec_first(DRMS_Record_t *rec, int wantprime)
00706 {
00707 int nprime;
00708 int status;
00709 DRMS_RecordSet_t *rs;
00710 char query[DRMS_MAXQUERYLEN];
00711 strcpy(query, rec->seriesinfo->seriesname);
00712 nprime = rec->seriesinfo->pidx_num;
00713 if (wantprime && nprime > 0)
00714
00715
00716 strcat(query, "[^]");
00717 else
00718 strcat(query, "[:#^]");
00719
00720 rs = drms_open_nrecords(rec->env, query, 1, &status);
00721
00722 return(rs);
00723 }
00724
00725
00726 DRMS_RecordSet_t *drms_find_rec_last(DRMS_Record_t *rec, int wantprime)
00727 {
00728 int nprime;
00729 int status;
00730 DRMS_RecordSet_t *rs;
00731 char query[DRMS_MAXQUERYLEN];
00732 strcpy(query, rec->seriesinfo->seriesname);
00733 nprime = rec->seriesinfo->pidx_num;
00734 if (wantprime && nprime > 0)
00735
00736
00737 strcat(query, "[$]");
00738 else
00739 strcat(query, "[:#$]");
00740 rs = drms_open_nrecords(rec->env, query, -1, &status);
00741 return(rs);
00742 }
00743
00744
00745 int wantowner = 0;
00746
00747
00748 char *drms_getseriesowner(DRMS_Env_t *drms_env, char *series, int *status)
00749 {
00750 char *nspace = NULL;
00751 char *relname = NULL;
00752 int istat = DRMS_SUCCESS;
00753 DB_Text_Result_t *qres = NULL;
00754 static char owner[256];
00755 owner[0] = '\0';
00756
00757 if (!get_namespace(series, &nspace, &relname))
00758 {
00759 char query[1024];
00760 strtolower(nspace);
00761 strtolower(relname);
00762
00763 snprintf(query, sizeof(query), "SELECT pg_catalog.pg_get_userbyid(T1.relowner) AS owner FROM pg_catalog.pg_class AS T1, (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = '%s') AS T2 WHERE T1.relnamespace = T2.oid AND T1.relname = '%s'", nspace, relname);
00764
00765 if ((qres = drms_query_txt(drms_env->session, query)) != NULL)
00766 {
00767 if (qres->num_cols == 1 && qres->num_rows == 1)
00768 strcpy(owner, qres->field[0][0]);
00769 db_free_text_result(qres);
00770 }
00771 }
00772 *status = owner[0] != 0;
00773 return(owner);
00774 }
00775
00776 static json_t *createJsonStringVal(const char *text)
00777 {
00778 json_t *rv = NULL;
00779 char *escText = NULL;
00780 char *jsonLibShouldReallyDeclareThisConst = NULL;
00781
00782 if (text && *text != '\0')
00783 {
00784 jsonLibShouldReallyDeclareThisConst = strdup(text);
00785 JSOC_INFO_ASSERT(jsonLibShouldReallyDeclareThisConst, "out of memory");
00786 escText = string_to_json(jsonLibShouldReallyDeclareThisConst);
00787 JSOC_INFO_ASSERT(escText, "out of memory");
00788 rv = json_new_string(escText);
00789 JSOC_INFO_ASSERT(rv, "out of memory");
00790 free(escText);
00791 escText = NULL;
00792 free(jsonLibShouldReallyDeclareThisConst);
00793 jsonLibShouldReallyDeclareThisConst = NULL;
00794 }
00795
00796 return rv;
00797 }
00798
00799 static int list_series_info(DRMS_Env_t *drms_env, DRMS_Record_t *rec, json_t *jroot, int followLinks, int useFitsKeyNames)
00800 {
00801 int error = 0;
00802
00803 DRMS_Keyword_t *key;
00804 DRMS_Segment_t *seg;
00805 DRMS_Link_t *link;
00806 HIterator_t *last = NULL;
00807 char intstring[100];
00808 char *notework;
00809 char *owner;
00810 json_t *indexarray = NULL;
00811 json_t *primearray = NULL;
00812 json_t *keyarray = NULL;
00813 json_t *segarray = NULL;
00814 json_t *linkarray = NULL;
00815 json_t *primeinfoarray = NULL;
00816 int npkeys;
00817 int status;
00818 char prevKeyName[DRMS_MAXNAMELEN] = "";
00819 char baseKeyName[DRMS_MAXNAMELEN];
00820 char fitsName[16];
00821 char *fitsValue = NULL;
00822 json_t *jsonVal = NULL;
00823 const char *keyNameOut = NULL;
00824 DRMS_Keyword_t *skey = NULL;
00825
00826
00827 notework = string_to_json(rec->seriesinfo->description);
00828 json_insert_pair_into_object(jroot, "note", json_new_string(notework));
00829 free(notework);
00830
00831 int16_t newSuRet = drms_series_getnewsuretention(rec->seriesinfo);
00832 int16_t stagingRet = drms_series_getstagingretention(rec->seriesinfo);
00833
00834 if (stagingRet == 0)
00835 {
00836 stagingRet = (int16_t)abs(STDRETENTION);
00837 }
00838
00839 snprintf(intstring, sizeof(intstring), "%hd", newSuRet);
00840 json_insert_pair_into_object(jroot, "retention", json_new_number(intstring));
00841 snprintf(intstring, sizeof(intstring), "%hd", stagingRet);
00842 json_insert_pair_into_object(jroot, "stagingretention", json_new_number(intstring));
00843 sprintf(intstring, "%d", rec->seriesinfo->unitsize);
00844 json_insert_pair_into_object(jroot, "unitsize", json_new_number(intstring));
00845 sprintf(intstring, "%d", rec->seriesinfo->archive);
00846 json_insert_pair_into_object(jroot, "archive", json_new_number(intstring));
00847 sprintf(intstring, "%d", rec->seriesinfo->tapegroup);
00848 json_insert_pair_into_object(jroot, "tapegroup", json_new_number(intstring));
00849
00850
00851 if (wantowner)
00852 {
00853 owner = string_to_json(drms_getseriesowner(drms_env, rec->seriesinfo->seriesname, &status));
00854 json_insert_pair_into_object(jroot, "owner", json_new_string(owner));
00855 free(owner);
00856 }
00857
00858
00859
00860
00861
00862 primearray = json_new_array();
00863 primeinfoarray = json_new_array();
00864 JSOC_INFO_ASSERT(primeinfoarray, "out of memory");
00865 npkeys = rec->seriesinfo->pidx_num;
00866
00867 if (npkeys > 0)
00868 {
00869 int i;
00870 json_t *primeinfo = NULL;
00871 char *jsonstr;
00872
00873 for (i=0; i<npkeys; i++)
00874 {
00875 json_t *primeinfo = json_new_object();
00876 XASSERT(primeinfo);
00877 DRMS_Keyword_t *pkey = NULL;
00878 DRMS_Keyword_t *stepKey = NULL;
00879 char rawval[128];
00880 int isSlotted = 0;
00881 pkey = rec->seriesinfo->pidx_keywords[i];
00882 error = 0;
00883
00884 if (!pkey || !pkey->info || *(pkey->info->name) == '\0')
00885 {
00886 fprintf(stderr, "Corrupt DRMS pkey keyword %s.\n", MISSING_KEY_NAME);
00887 error = 1;
00888 }
00889
00890 if (!error)
00891 {
00892 if (drms_keyword_isindex(pkey))
00893 {
00894 isSlotted = 1;
00895 skey = drms_keyword_slotfromindex(pkey);
00896
00897 if (!skey || !skey->info || *(skey->info->name) == '\0')
00898 {
00899 fprintf(stderr, "Corrupt DRMS index keyword %s.\n", pkey->info->name);
00900 error = 1;
00901 }
00902
00903 if (!error)
00904 {
00905 if (USE_FITS_NAMES_FOR_COLUMNS && useFitsKeyNames)
00906 {
00907 if (fitsexport_getmappedextkeyname(skey, NULL, NULL, fitsName, sizeof(fitsName)) && *fitsName != '\0')
00908 {
00909 keyNameOut = fitsName;
00910 }
00911 else
00912 {
00913 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", skey->info->name);
00914 keyNameOut = MISSING_KEY_NAME;
00915 error = 1;
00916 }
00917 }
00918 else
00919 {
00920 keyNameOut = skey->info->name;
00921 }
00922 }
00923 else
00924 {
00925
00926 keyNameOut = MISSING_KEY_NAME;
00927 }
00928
00929 stepKey = drms_keyword_stepfromvalkey(skey);
00930
00931 if (!stepKey || !stepKey->info || *(stepKey->info->name) == '\0')
00932 {
00933 fprintf(stderr, "Corrupt DRMS step keyword for keyword %s.\n", skey->info->name);
00934 error = 1;
00935 }
00936
00937 if (!error)
00938 {
00939 if (USE_FITS_NAMES_FOR_COLUMNS && useFitsKeyNames)
00940 {
00941 JSOC_INFO_ASSERT(fitsValue == NULL, "about to leak");
00942 fitsexport_getmappedextkeyvalue(stepKey, &fitsValue);
00943
00944 if (fitsValue)
00945 {
00946 snprintf(rawval, sizeof(rawval), "%s", fitsValue);
00947 free(fitsValue);
00948 fitsValue = NULL;
00949 }
00950 else
00951 {
00952 fprintf(stderr, "Unable to map DRMS keyword value %s to FITS keyword value.\n", stepKey->info->name);
00953 snprintf(rawval, sizeof(rawval), "%s", MISSING_KEY_VALUE);
00954 error = 1;
00955 }
00956 }
00957 else
00958 {
00959 drms_keyword_snprintfval(stepKey, rawval, sizeof(rawval));
00960 }
00961 }
00962 else
00963 {
00964 snprintf(rawval, sizeof(rawval), "%s", MISSING_KEY_VALUE);
00965 }
00966 }
00967 else
00968 {
00969
00970 if (USE_FITS_NAMES_FOR_COLUMNS && useFitsKeyNames)
00971 {
00972 if (fitsexport_getmappedextkeyname(pkey, NULL, NULL, fitsName, sizeof(fitsName)) && *fitsName != '\0')
00973 {
00974 keyNameOut = fitsName;
00975 }
00976 else
00977 {
00978 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", pkey->info->name);
00979 keyNameOut = MISSING_KEY_NAME;
00980 error = 1;
00981 }
00982 }
00983 else
00984 {
00985 keyNameOut = pkey->info->name;
00986 }
00987 }
00988 }
00989 else
00990 {
00991
00992 keyNameOut = MISSING_KEY_NAME;
00993 }
00994
00995
00996 jsonVal = createJsonStringVal(keyNameOut);
00997 json_insert_pair_into_object(primeinfo, "name", jsonVal);
00998 jsonVal = NULL;
00999
01000
01001 jsonVal = isSlotted ? json_new_number("1") : json_new_number("0");
01002 JSOC_INFO_ASSERT(jsonVal, "out of memory");
01003 json_insert_pair_into_object(primeinfo, "slotted", jsonVal);
01004 jsonVal = NULL;
01005
01006
01007 if (stepKey)
01008 {
01009 jsonVal = createJsonStringVal(rawval);
01010 json_insert_pair_into_object(primeinfo, "step", jsonVal);
01011 jsonVal = NULL;
01012 }
01013
01014 json_insert_child(primeinfoarray, primeinfo);
01015
01016
01017 jsonVal = createJsonStringVal(keyNameOut);
01018 json_insert_child(primearray, jsonVal);
01019 jsonVal = NULL;
01020 }
01021
01022 error = 0;
01023 }
01024 else
01025 {
01026 jsonVal = json_new_null();
01027 XASSERT(jsonVal);
01028 json_insert_child(primearray, jsonVal);
01029 jsonVal = json_new_null();
01030 XASSERT(jsonVal);
01031 json_insert_child(primeinfoarray, jsonVal);
01032 jsonVal = NULL;
01033 }
01034
01035 json_insert_pair_into_object(jroot, "primekeys", primearray);
01036 json_insert_pair_into_object(jroot, "primekeysinfo", primeinfoarray);
01037
01038
01039
01040 indexarray = json_new_array();
01041 XASSERT(indexarray);
01042
01043 if (rec->seriesinfo->dbidx_num > 0)
01044 {
01045 int i;
01046
01047 for (i=0; i<rec->seriesinfo->dbidx_num; i++)
01048 {
01049 error = 0;
01050 key = rec->seriesinfo->dbidx_keywords[i];
01051
01052 if (drms_keyword_isindex(key))
01053 {
01054 skey = drms_keyword_slotfromindex(key);
01055
01056 if (!skey || !skey->info || *(skey->info->name) == '\0')
01057 {
01058 fprintf(stderr, "Corrupt DRMS index keyword %s.\n", key->info->name);
01059 error = 1;
01060 }
01061
01062 if (!error)
01063 {
01064 if (USE_FITS_NAMES_FOR_COLUMNS && useFitsKeyNames)
01065 {
01066 if (fitsexport_getmappedextkeyname(skey, NULL, NULL, fitsName, sizeof(fitsName)) && *fitsName != '\0')
01067 {
01068 keyNameOut = fitsName;
01069 }
01070 else
01071 {
01072 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", skey->info->name);
01073 keyNameOut = MISSING_KEY_NAME;
01074 error = 1;
01075 }
01076 }
01077 else
01078 {
01079 keyNameOut = skey->info->name;
01080 }
01081 }
01082 else
01083 {
01084
01085 keyNameOut = MISSING_KEY_NAME;
01086 }
01087 }
01088 else
01089 {
01090 if (!error)
01091 {
01092 if (USE_FITS_NAMES_FOR_COLUMNS && useFitsKeyNames)
01093 {
01094 if (fitsexport_getmappedextkeyname(key, NULL, NULL, fitsName, sizeof(fitsName)) && *fitsName != '\0')
01095 {
01096 keyNameOut = fitsName;
01097 }
01098 else
01099 {
01100 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", key->info->name);
01101 keyNameOut = MISSING_KEY_NAME;
01102 error = 1;
01103 }
01104 }
01105 else
01106 {
01107 keyNameOut = key->info->name;
01108 }
01109 }
01110 else
01111 {
01112
01113 keyNameOut = MISSING_KEY_NAME;
01114 }
01115 }
01116
01117 jsonVal = createJsonStringVal(keyNameOut);
01118 json_insert_child(indexarray, jsonVal);
01119 jsonVal = NULL;
01120 }
01121 }
01122 else
01123 {
01124 jsonVal = json_new_null();
01125 XASSERT(jsonVal);
01126 json_insert_child(indexarray, jsonVal);
01127 jsonVal = NULL;
01128 }
01129
01130 json_insert_pair_into_object(jroot, "dbindex", indexarray);
01131
01132 if (DEBUG) fprintf(stderr," starting all keywords\n");
01133
01134 json_t *keyinfo= NULL;
01135 json_t *keytype = NULL;
01136 json_t *defval = NULL;
01137 json_t *recscope = NULL;
01138 char rawval[128];
01139 char *jsonstr = NULL;
01140 char *typework = NULL;
01141 char *scopework = NULL;
01142 char *unitswork = NULL;
01143 char *defvalwork = NULL;
01144
01145
01146 keyarray = json_new_array();
01147 XASSERT(keyarray);
01148
01149
01150
01151
01152
01153
01154 if (useFitsKeyNames)
01155 {
01156 DRMS_Record_t *jsdTemplate = NULL;
01157 DRMS_Keyword_t *jsdKeys = NULL;
01158 char *typeStr = NULL;
01159 char *scopeStr = NULL;
01160 char *defStr = NULL;
01161 char *unitsStr = NULL;
01162 char *noteStr = NULL;
01163
01164 jsdTemplate = drms_create_jsdtemplate_record(drms_env, rec->seriesinfo->seriesname, &status);
01165 if (!jsdTemplate || status != DRMS_SUCCESS)
01166 {
01167 error = 1;
01168 }
01169 else
01170 {
01171 while ((key = drms_record_nextkey(jsdTemplate, &last, 0)))
01172 {
01173 error = 0;
01174
01175 if (!key->info || *(key->info->name) == '\0')
01176 {
01177 fprintf(stderr, "Corrupt DRMS keyword.\n");
01178 error = 1;
01179 continue;
01180 }
01181
01182 if (drms_keyword_getimplicit(key))
01183 {
01184
01185 continue;
01186 }
01187
01188 keyinfo = json_new_object();
01189 XASSERT(keyinfo);
01190
01191 if (fitsexport_getmappedextkeyname(key, NULL, NULL, fitsName, sizeof(fitsName)) && *fitsName != '\0')
01192 {
01193 keyNameOut = fitsName;
01194 }
01195 else
01196 {
01197 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", key->info->name);
01198 keyNameOut = MISSING_KEY_NAME;
01199 error = 1;
01200 }
01201
01202 jsonVal = createJsonStringVal(keyNameOut);
01203 json_insert_pair_into_object(keyinfo, "name", jsonVal);
01204 jsonVal = NULL;
01205
01206 if (key->info->islink)
01207 {
01208
01209 char keylinkMap[DRMS_MAXLINKNAMELEN + DRMS_MAXKEYNAMELEN + 16];
01210 char *tmpstr = NULL;
01211 json_t *linkinfo = NULL;
01212 int lnkstat = DRMS_SUCCESS;
01213 DRMS_Keyword_t *linkedkw = NULL;
01214
01215
01216
01217 linkedkw = drms_jsd_template_keyword_followlink(key, &lnkstat);
01218
01219 if (lnkstat != DRMS_SUCCESS || !linkedkw || !linkedkw->info || *(linkedkw->info->name) == '\0')
01220 {
01221 fprintf(stderr, "Cannot obtain target keyword for %s.\n", key->info->name);
01222 error = 1;
01223 }
01224
01225 if (!error)
01226 {
01227 if (fitsexport_getmappedextkeyname(linkedkw, NULL, NULL, fitsName, sizeof(fitsName)) && *fitsName != '\0')
01228 {
01229 keyNameOut = fitsName;
01230 }
01231 else
01232 {
01233 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", key->info->target_key);
01234 keyNameOut = MISSING_KEY_NAME;
01235 error = 1;
01236 }
01237 }
01238 else
01239 {
01240 keyNameOut = MISSING_KEY_NAME;
01241 }
01242
01243 snprintf(keylinkMap, sizeof(keylinkMap), "%s->%s", key->info->linkname, keyNameOut);
01244 jsonVal = createJsonStringVal(keylinkMap);
01245 json_insert_pair_into_object(keyinfo, "linkinfo", linkinfo);
01246 jsonVal = NULL;
01247
01248
01249 if (lnkstat == DRMS_SUCCESS && linkedkw)
01250 {
01251 typeStr = strdup(drms_type2str(linkedkw->info->type));
01252 scopeStr = strdup(drms_keyword_getrecscopestr(linkedkw, NULL));
01253
01254 JSOC_INFO_ASSERT(typeStr, "out of memory");
01255 JSOC_INFO_ASSERT(scopeStr, "out of memory");
01256
01257 fitsexport_getmappedextkeyvalue(linkedkw, &fitsValue);
01258
01259 if (fitsValue)
01260 {
01261 snprintf(rawval, sizeof(rawval), "%s", fitsValue);
01262 free(fitsValue);
01263 fitsValue = NULL;
01264 }
01265 else
01266 {
01267 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", linkedkw->info->name);
01268 snprintf(rawval, sizeof(rawval), "%s", MISSING_KEY_VALUE);
01269 error = 1;
01270 }
01271
01272 defStr = strdup(rawval);
01273 JSOC_INFO_ASSERT(defStr, "out of memory");
01274 unitsStr = strdup(linkedkw->info->unit);
01275 JSOC_INFO_ASSERT(unitsStr, "out of memory");
01276
01277 if (*(key->info->description) == '\0' || *(key->info->description) == ' ')
01278 {
01279 noteStr = strdup(linkedkw->info->description);
01280 }
01281 else
01282 {
01283 noteStr = strdup(key->info->description);
01284 }
01285
01286 JSOC_INFO_ASSERT(noteStr, "out of memory");
01287 }
01288 else
01289 {
01290 typeStr = strdup("link");
01291 JSOC_INFO_ASSERT(typeStr, "out of memory");
01292
01293
01294
01295 scopeStr = strdup("error following link");
01296 JSOC_INFO_ASSERT(scopeStr, "out of memory");
01297 defStr = string_to_json("error following link");
01298 JSOC_INFO_ASSERT(defStr, "out of memory");
01299 unitsStr = string_to_json("error following link");
01300 JSOC_INFO_ASSERT(unitsStr, "out of memory");
01301 noteStr = string_to_json("error following link");
01302 JSOC_INFO_ASSERT(noteStr, "out of memory");
01303 }
01304 }
01305 else
01306 {
01307
01308 typeStr = strdup(drms_type2str(key->info->type));
01309 JSOC_INFO_ASSERT(typeStr, "out of memory");
01310 scopeStr = strdup(drms_keyword_getrecscopestr(key, NULL));
01311 JSOC_INFO_ASSERT(scopeStr, "out of memory");
01312
01313 fitsexport_getmappedextkeyvalue(key, &fitsValue);
01314
01315 if (fitsValue)
01316 {
01317 snprintf(rawval, sizeof(rawval), "%s", fitsValue);
01318 free(fitsValue);
01319 fitsValue = NULL;
01320 }
01321 else
01322 {
01323 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", key->info->name);
01324 snprintf(rawval, sizeof(rawval), "%s", MISSING_KEY_VALUE);
01325 error = 1;
01326 }
01327
01328 defStr = strdup(rawval);
01329 JSOC_INFO_ASSERT(defStr, "out of memory");
01330 unitsStr = strdup(key->info->unit);
01331 JSOC_INFO_ASSERT(unitsStr, "out of memory");
01332 noteStr = strdup(key->info->description);
01333 JSOC_INFO_ASSERT(noteStr, "out of memory");
01334 }
01335
01336 jsonVal = createJsonStringVal(typeStr);
01337 json_insert_pair_into_object(keyinfo, "type", jsonVal);
01338 jsonVal = NULL;
01339
01340
01341 jsonVal = createJsonStringVal(scopeStr);
01342 json_insert_pair_into_object(keyinfo, "recscope", jsonVal);
01343 jsonVal = NULL;
01344
01345 jsonVal = createJsonStringVal(defStr);
01346 json_insert_pair_into_object(keyinfo, "defval", jsonVal);
01347 jsonVal = NULL;
01348
01349 jsonVal = createJsonStringVal(unitsStr);
01350 json_insert_pair_into_object(keyinfo, "units", jsonVal);
01351 jsonVal = NULL;
01352
01353 jsonVal = createJsonStringVal(noteStr);
01354 XASSERT(jsonVal);
01355 json_insert_pair_into_object(keyinfo, "note", jsonVal);
01356 jsonVal = NULL;
01357
01358 json_insert_child(keyarray, keyinfo);
01359 }
01360
01361 if (last)
01362 {
01363 hiter_destroy(&last);
01364 }
01365
01366 drms_destroy_jsdtemplate_record(&jsdTemplate);
01367 }
01368 }
01369 else
01370 {
01371
01372
01373
01374
01375
01376 while ((key = drms_record_nextkey(rec, &last, 0)))
01377 {
01378 int persegment = key->info->kwflags & kKeywordFlag_PerSegment;
01379
01380 if (DEBUG) fprintf(stderr," starting keyword %s\n",key->info->name);
01381
01382 if (persegment)
01383 {
01384 char *underscore;
01385
01386 strcpy(baseKeyName, key->info->name);
01387 underscore = rindex(baseKeyName, '_');
01388 if (underscore) *underscore = '\0';
01389 if (strcmp(prevKeyName, baseKeyName) == 0)
01390 continue;
01391 strcpy(prevKeyName, baseKeyName);
01392 }
01393
01394 keyinfo = json_new_object();
01395 json_insert_pair_into_object(keyinfo, "name", json_new_string(persegment ? baseKeyName : key->info->name));
01396
01397 if (key->info->islink)
01398 {
01399
01400 char linknames[100], *tmpstr;
01401 json_t *linkinfo;
01402 sprintf(linknames,"%s->%s", key->info->linkname, key->info->target_key);
01403 tmpstr = string_to_json(linknames);
01404 linkinfo = json_new_string(tmpstr);
01405 json_insert_pair_into_object(keyinfo, "linkinfo", linkinfo);
01406 free(tmpstr);
01407
01408
01409 int lnkstat = DRMS_SUCCESS;
01410 DRMS_Keyword_t *linkedkw = drms_template_keyword_followlink(key, &lnkstat);
01411
01412
01413 if (lnkstat == DRMS_SUCCESS && linkedkw)
01414 {
01415 keytype = json_new_string(drms_type_names[linkedkw->info->type]);
01416 scopework = string_to_json((char *)drms_keyword_getrecscopestr(linkedkw, NULL));
01417 drms_keyword_snprintfval(linkedkw, rawval, sizeof(rawval));
01418 defvalwork = string_to_json(rawval);
01419 unitswork = string_to_json(linkedkw->info->unit);
01420
01421 if (*(key->info->description) == '\0' || *(key->info->description) == ' ')
01422 notework = string_to_json(linkedkw->info->description);
01423 else
01424 notework = string_to_json(key->info->description);
01425 }
01426 else
01427 {
01428 keytype = json_new_string("link");
01429
01430
01431
01432 scopework = string_to_json("error following link");
01433 defvalwork = string_to_json("error following link");
01434 unitswork = string_to_json("error following link");
01435 notework = string_to_json("error following link");
01436 }
01437 }
01438 else
01439 {
01440
01441 keytype = json_new_string(drms_type_names[key->info->type]);
01442 if (persegment)
01443 scopework = string_to_json("segment");
01444 else
01445 scopework = string_to_json((char *)drms_keyword_getrecscopestr(key, NULL));
01446 drms_keyword_snprintfval(key, rawval, sizeof(rawval));
01447 defvalwork = string_to_json(rawval);
01448 unitswork = string_to_json(key->info->unit);
01449 notework = string_to_json(key->info->description);
01450 }
01451
01452 json_insert_pair_into_object(keyinfo, "type", keytype);
01453
01454
01455 XASSERT(scopework);
01456 json_insert_pair_into_object(keyinfo, "recscope", json_new_string(scopework));
01457 free(scopework);
01458 scopework = NULL;
01459
01460 XASSERT(defvalwork);
01461 json_insert_pair_into_object(keyinfo, "defval", json_new_string(defvalwork));
01462 free(defvalwork);
01463 defvalwork = NULL;
01464
01465 XASSERT(unitswork);
01466 json_insert_pair_into_object(keyinfo, "units", json_new_string(unitswork));
01467 free(unitswork);
01468 unitswork = NULL;
01469
01470 XASSERT(notework);
01471 json_insert_pair_into_object(keyinfo, "note", json_new_string(notework));
01472 free(notework);
01473 notework = NULL;
01474
01475 json_insert_child(keyarray, keyinfo);
01476 }
01477
01478 if (last)
01479 {
01480 hiter_destroy(&last);
01481 }
01482 }
01483
01484
01485 json_insert_pair_into_object(jroot, "keywords", keyarray);
01486 if (DEBUG) fprintf(stderr," done with keywords, start segments\n");
01487
01488
01489 segarray = json_new_array();
01490 if (rec->segments.num_total)
01491 {
01492 DRMS_Segment_t *oseg = NULL;
01493
01494 while ((seg = drms_record_nextseg(rec, &last, 0)))
01495 {
01496 oseg = seg;
01497
01498 if (followLinks && seg->info->islink)
01499 {
01500
01501
01502 int lnkstat = DRMS_SUCCESS;
01503
01504 seg = drms_template_segment_followlink(seg, &lnkstat);
01505 if (lnkstat)
01506 {
01507 continue;
01508 }
01509 }
01510
01511
01512 json_t *seginfo = json_new_object();
01513 int naxis = seg->info->naxis;
01514
01515
01516 json_insert_pair_into_object(seginfo, "name", json_new_string(oseg->info->name));
01517 if (!followLinks && seg->info->islink)
01518 {
01519 char linkinfo[DRMS_MAXNAMELEN+10];
01520 sprintf(linkinfo, "link via %s", seg->info->linkname);
01521 json_insert_pair_into_object(seginfo, "type", json_new_string(drms_type_names[seg->info->type]));
01522 json_insert_pair_into_object(seginfo, "units", json_new_null());
01523 json_insert_pair_into_object(seginfo, "protocol", json_new_string(linkinfo));
01524 json_insert_pair_into_object(seginfo, "dims", json_new_null());
01525 }
01526 else
01527 {
01528 char prot[DRMS_MAXNAMELEN];
01529 char diminfo[160];
01530 int iaxis;
01531 strcpy(prot, drms_prot2str(seg->info->protocol));
01532 json_insert_pair_into_object(seginfo, "type", json_new_string(drms_type_names[seg->info->type]));
01533 json_insert_pair_into_object(seginfo, "units", json_new_string(seg->info->unit));
01534 json_insert_pair_into_object(seginfo, "protocol", json_new_string(prot));
01535 diminfo[0] = '\0';
01536 for (iaxis=0; iaxis<naxis; iaxis++)
01537 {
01538 if (iaxis != 0)
01539 strcat(diminfo,"x");
01540 if (seg->info->scope == DRMS_VARDIM)
01541 strcat(diminfo,"VAR");
01542 else
01543 {
01544 char size[10];
01545 sprintf(size,"%d",seg->axis[iaxis]);
01546 strcat(diminfo,size);
01547 }
01548 }
01549 json_insert_pair_into_object(seginfo, "dims", json_new_string(diminfo));
01550 }
01551 notework = string_to_json(seg->info->description);
01552 json_insert_pair_into_object(seginfo, "note", json_new_string(notework));
01553 free(notework);
01554 json_insert_child(segarray, seginfo);
01555 }
01556 }
01557
01558
01559 json_insert_pair_into_object(jroot, "segments", segarray);
01560
01561 if (DEBUG) fprintf(stderr," done with segments, start links\n");
01562
01563 linkarray = json_new_array();
01564 if (rec->links.num_total)
01565 {
01566 if (last)
01567 {
01568 hiter_destroy(&last);
01569 }
01570
01571 while ((link = drms_record_nextlink(rec, &last)))
01572 {
01573 if (DEBUG) fprintf(stderr," link: %s\n",link->info->name);
01574 json_t *linkinfo = json_new_object();
01575 json_insert_pair_into_object(linkinfo, "name", json_new_string(link->info->name));
01576 json_insert_pair_into_object(linkinfo, "target", json_new_string(link->info->target_series));
01577 json_insert_pair_into_object(linkinfo, "kind", json_new_string(link->info->type == STATIC_LINK ? "STATIC" : "DYNAMIC"));
01578 notework = string_to_json(link->info->description);
01579 json_insert_pair_into_object(linkinfo, "note", json_new_string(notework));
01580 free(notework);
01581 json_insert_child(linkarray,linkinfo);
01582 }
01583 }
01584
01585
01586 json_insert_pair_into_object(jroot, "links", linkarray);
01587
01588 if (last)
01589 {
01590 hiter_destroy(&last);
01591 }
01592
01593 return error;
01594 }
01595
01596 static int get_series_stats(DRMS_Record_t *rec, json_t *jroot)
01597 {
01598 DRMS_RecordSet_t *rs;
01599 int nprime;
01600 int status;
01601 char query[DRMS_MAXQUERYLEN];
01602 json_t *interval = json_new_object();
01603
01604 nprime = rec->seriesinfo->pidx_num;
01605 if (nprime > 0)
01606 sprintf(query,"%s[^]", rec->seriesinfo->seriesname);
01607 else
01608 sprintf(query,"%s[:#^]", rec->seriesinfo->seriesname);
01609 rs = drms_open_nrecords(rec->env, query, 1, &status);
01610
01611 if (status == DRMS_ERROR_QUERYFAILED)
01612 {
01613 if (rs)
01614 {
01615 drms_free_records(rs);
01616 }
01617
01618 return status;
01619 }
01620
01621
01622 int shadowStat;
01623 char shadowStr[16];
01624 int hasShadow;
01625
01626 if (wantowner)
01627 {
01628
01629
01630
01631
01632
01633 hasShadow= drms_series_shadowexists(rec->env, rec->seriesinfo->seriesname, &shadowStat);
01634
01635 if (shadowStat)
01636 {
01637 snprintf(shadowStr, sizeof(shadowStr), "?");
01638 }
01639 else
01640 {
01641 snprintf(shadowStr, sizeof(shadowStr), "%s", hasShadow ? "yes" : "no");
01642 }
01643 }
01644
01645 if (!rs || rs->n < 1)
01646 {
01647 json_insert_pair_into_object(interval, "FirstRecord", json_new_string("NA"));
01648 json_insert_pair_into_object(interval, "FirstRecnum", json_new_string("NA"));
01649 json_insert_pair_into_object(interval, "LastRecord", json_new_string("NA"));
01650 json_insert_pair_into_object(interval, "LastRecnum", json_new_string("NA"));
01651 json_insert_pair_into_object(interval, "MaxRecnum", json_new_number("0"));
01652 if (wantowner)
01653 {
01654 json_insert_pair_into_object(interval, "HasShadow", json_new_string(shadowStr));
01655 }
01656
01657 if (rs) drms_free_records(rs);
01658 json_insert_pair_into_object(jroot, "Interval", interval);
01659 return DRMS_SUCCESS;
01660 }
01661 else
01662 {
01663 char recquery[DRMS_MAXQUERYLEN];
01664 char *jsonquery;
01665 char val[100];
01666 int status;
01667 drms_sprint_rec_query(recquery,rs->records[0]);
01668 jsonquery = string_to_json(recquery);
01669 status = json_insert_pair_into_object(interval, "FirstRecord", json_new_string(jsonquery));
01670 if (status != JSON_OK) fprintf(stderr, "json_insert_pair_into_object, status=%d, text=%s\n",status,jsonquery);
01671 free(jsonquery);
01672 sprintf(val,"%lld", rs->records[0]->recnum);
01673 json_insert_pair_into_object(interval, "FirstRecnum", json_new_number(val));
01674 drms_free_records(rs);
01675
01676 if (nprime > 0)
01677 sprintf(query,"%s[$]", rec->seriesinfo->seriesname);
01678 else
01679 sprintf(query,"%s[:#$]", rec->seriesinfo->seriesname);
01680 rs = drms_open_nrecords(rec->env, query, -1, &status);
01681
01682 if (status == DRMS_ERROR_QUERYFAILED)
01683 {
01684 if (rs)
01685 {
01686 drms_free_records(rs);
01687 }
01688
01689 return status;
01690 }
01691
01692 drms_sprint_rec_query(recquery,rs->records[0]);
01693 jsonquery = string_to_json(recquery);
01694 json_insert_pair_into_object(interval, "LastRecord", json_new_string(jsonquery));
01695 free(jsonquery);
01696 sprintf(val,"%lld", rs->records[0]->recnum);
01697 json_insert_pair_into_object(interval, "LastRecnum", json_new_number(val));
01698 drms_free_records(rs);
01699
01700 sprintf(query,"%s[:#$]", rec->seriesinfo->seriesname);
01701 rs = drms_open_records(rec->env, query, &status);
01702
01703 if (status == DRMS_ERROR_QUERYFAILED)
01704 {
01705 if (rs)
01706 {
01707 drms_free_records(rs);
01708 }
01709
01710 return status;
01711 }
01712
01713 sprintf(val,"%lld", rs->records[0]->recnum);
01714 json_insert_pair_into_object(interval, "MaxRecnum", json_new_number(val));
01715 if (wantowner)
01716 {
01717 json_insert_pair_into_object(interval, "HasShadow", json_new_string(shadowStr));
01718 }
01719 drms_free_records(rs);
01720 }
01721 json_insert_pair_into_object(jroot, "Interval", interval);
01722 return 0;
01723 }
01724
01725 void json_insert_runtime(json_t *jroot, double StartTime)
01726 {
01727 char runtime[100];
01728 double EndTime;
01729 struct timeval thistv;
01730 gettimeofday(&thistv, NULL);
01731 EndTime = thistv.tv_sec + thistv.tv_usec/1000000.0;
01732 sprintf(runtime,"%0.3f",EndTime - StartTime);
01733 json_insert_pair_into_object(jroot, "runtime", json_new_number(runtime));
01734 }
01735
01736 #define LOGFILE "/home/jsoc/exports/logs/fetch_log"
01737 #define kLockFile "/home/jsoc/exports/tmp/lock.txt"
01738
01739
01740 void report_summary(const char *host, double StartTime, const char *remote_IP, const char *op, const char *ds, int n, int status)
01741 {
01742 FILE *log;
01743 int sleeps;
01744 double EndTime;
01745 struct timeval thistv;
01746 struct stat stbuf;
01747 int mustchmodlck = (stat(kLockFile, &stbuf) != 0);
01748 int mustchmodlog = (stat(LOGFILE, &stbuf) != 0);
01749 int lockfd = open(kLockFile, O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG);
01750
01751 if (lockfd >= 0)
01752 {
01753 gettimeofday(&thistv, NULL);
01754 EndTime = thistv.tv_sec + thistv.tv_usec/1000000.0;
01755
01756 for(sleeps=0; lockf(lockfd,F_TLOCK,0); sleeps++)
01757 {
01758 if (sleeps >= 5)
01759 {
01760 fprintf(stderr,"Lock stuck on %s, no report made.\n", LOGFILE);
01761 lockf(lockfd,F_ULOCK,0);
01762 return;
01763 }
01764 sleep(1);
01765 }
01766
01767 log = fopen(LOGFILE,"a");
01768
01769 if (log)
01770 {
01771 fprintf(log, "host='%s'\t",host);
01772 fprintf(log, "lag=%0.3f\t",EndTime - StartTime);
01773 fprintf(log, "IP='%s'\t",remote_IP);
01774 fprintf(log, "op='%s'\t",op);
01775 fprintf(log, "ds='%s'\t",ds);
01776 fprintf(log, "n=%d\t",n);
01777 fprintf(log, "status=%d\n",status);
01778 fflush(log);
01779 if (mustchmodlog)
01780 {
01781 fchmod(fileno(log), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
01782 }
01783 fclose(log);
01784 }
01785
01786 if (mustchmodlck)
01787 {
01788 fchmod(lockfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
01789 }
01790 lockf(lockfd,F_ULOCK,0);
01791 close(lockfd);
01792 }
01793 else
01794 {
01795 fprintf(stderr, "Unable to open lock file for writing: %s.\n", kLockFile);
01796 }
01797 }
01798
01799
01800 int OnSIGINT(void *data)
01801 {
01802 printf("Content-Type: application/json\n\n{\"status\":-1}\n");
01803 return 0;
01804 }
01805
01806 static int SetWebArg(Q_ENTRY *req, const char *key, char **arglist, size_t *size)
01807 {
01808 char *value = NULL;
01809 char buf[1024];
01810
01811 if (req)
01812 {
01813 value = (char *)qEntryGetStr(req, key);
01814 if (value)
01815 {
01816 if (!cmdparams_set(&cmdparams, key, value))
01817 {
01818
01819
01820
01821
01822 return(1);
01823 }
01824
01825
01826
01827 snprintf(buf, sizeof(buf), "%s='%s' ", key, value);
01828 *arglist = base_strcatalloc(*arglist, buf, size);
01829 }
01830 }
01831
01832 return(0);
01833 }
01834
01835
01836 int DoIt(void)
01837 {
01838 const char *op;
01839 const char *in;
01840 char *keylist;
01841 char *seglist;
01842 char *linklist;
01843 char *web_query;
01844 const char *Remote_Address;
01845 const char *Server;
01846 int followLinks = 0;
01847 int from_web, keys_listed, segs_listed, links_listed;
01848 int max_recs = 0;
01849 struct timeval thistv;
01850 double StartTime;
01851 CleanerData_t cleaner;
01852 int useFitsKeyNames = 0;
01853 int skipRunTime = 0;
01854 LinkedList_t *reqSegs = NULL;
01855 LinkedList_t *reqKeys = NULL;
01856 LinkedList_t *reqLinks = NULL;
01857 json_t *recArray = NULL;
01858 char *jsonOut = NULL;
01859 char *final_json = NULL;
01860
01861 int missingKeyNumber = 0;
01862 int missingSegNumber = 0;
01863 int missingLinkNumber = 0;
01864 char missingKeyNameBuf[DRMS_MAXKEYNAMELEN] = { 0 };
01865 char missingSegNameBuf[DRMS_MAXSEGNAMELEN] = { 0 };
01866 char missingLinkNameBuf[DRMS_MAXLINKNAMELEN] = { 0 };
01867
01868 if (nice_intro ()) return (0);
01869
01870
01871
01872 cleaner.cb = (pFn_Cleaner_t)&OnSIGINT;
01873 cleaner.data = NULL;
01874 drms_server_registercleaner(drms_env, &cleaner);
01875
01876 gettimeofday(&thistv, NULL);
01877 StartTime = thistv.tv_sec + thistv.tv_usec/1000000.0;
01878
01879 web_query = strdup (cmdparams_get_str (&cmdparams, "QUERY_STRING", NULL));
01880 from_web = strcmp (web_query, "Not Specified") != 0;
01881
01882 int postorget = 0;
01883 char *webarglist = NULL;
01884 size_t webarglistsz;
01885
01886 if (getenv("REQUEST_METHOD"))
01887 {
01888 postorget = (strcasecmp(getenv("REQUEST_METHOD"), "POST") == 0 || strcasecmp(getenv("REQUEST_METHOD"), "GET") == 0);
01889 }
01890
01891 if (from_web)
01892 {
01893 Q_ENTRY *req = NULL;
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909 if (!getenv("QUERY_STRING"))
01910 {
01911
01912 if (!postorget)
01913 {
01914
01915 setenv("QUERY_STRING", web_query, 1);
01916
01917
01918 setenv("REQUEST_METHOD", "GET", 1);
01919 }
01920 }
01921
01922
01923
01924
01925
01926
01927 webarglistsz = 2048;
01928 webarglist = (char *)malloc(webarglistsz);
01929 *webarglist = '\0';
01930
01931 req = qCgiRequestParseQueries(NULL, NULL);
01932 if (req)
01933 {
01934
01935 if (SetWebArg(req, "op", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01936 if (SetWebArg(req, "ds", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01937 if (SetWebArg(req, "key", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01938 if (SetWebArg(req, "seg", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01939 if (SetWebArg(req, "link", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01940 if (SetWebArg(req, "n", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01941 if (SetWebArg(req, "userhandle", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01942 if (SetWebArg(req, "l", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01943 if (SetWebArg(req, "REMOTE_ADDR", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01944 if (SetWebArg(req, "SERVER_NAME", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01945 if (SetWebArg(req, "o", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01946 if (SetWebArg(req, "R", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01947 if (SetWebArg(req, "f", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01948 if (SetWebArg(req, "r", &webarglist, &webarglistsz)) JSONDIE("Bad QUERY_STRING");
01949
01950
01951 cmdparams_set (&cmdparams,"z", "1");
01952
01953 qEntryFree(req);
01954 }
01955
01956 free(webarglist);
01957 webarglist = NULL;
01958 }
01959
01960 if (web_query)
01961 {
01962 free(web_query);
01963 web_query = NULL;
01964 }
01965
01966 op = cmdparams_get_str (&cmdparams, "op", NULL);
01967 in = cmdparams_get_str (&cmdparams, "ds", NULL);
01968 keylist = strdup (cmdparams_get_str (&cmdparams, "key", NULL));
01969 seglist = strdup (cmdparams_get_str (&cmdparams, "seg", NULL));
01970 linklist = strdup (cmdparams_get_str (&cmdparams, "link", NULL));
01971 max_recs = cmdparams_get_int (&cmdparams, "n", NULL);
01972
01973 keys_listed = strcmp (keylist, "Not Specified");
01974 segs_listed = strcmp (seglist, "Not Specified");
01975 links_listed = strcmp (linklist, "Not Specified");
01976 userhandle = cmdparams_get_str (&cmdparams, "userhandle", NULL);
01977 followLinks = cmdparams_isflagset(&cmdparams, "l");
01978 Remote_Address = cmdparams_get_str(&cmdparams, "REMOTE_ADDR", NULL);
01979 Server = cmdparams_get_str(&cmdparams, "SERVER_NAME", NULL);
01980
01981
01982 wantowner = cmdparams_get_int (&cmdparams, "o", NULL);
01983
01984 useFitsKeyNames = cmdparams_isflagset(&cmdparams, "f");
01985 skipRunTime = cmdparams_isflagset(&cmdparams, "r");
01986
01987
01988 if (strcmp(userhandle, "Not Specified") != 0)
01989 manage_userhandle(1, userhandle);
01990 else
01991 userhandle = "NoHandle";
01992
01993
01994 if (strcmp(op,"series_struct") == 0)
01995 {
01996 char *p, *seriesname;
01997 json_t *jroot;
01998 DRMS_Record_t *rec;
01999 int status=0;
02000
02001 seriesname = strdup (in);
02002 if ((p = index(seriesname,'['))) *p = '\0';
02003 if ((p = index(seriesname,'{'))) *p = '\0';
02004 rec = drms_template_record (drms_env, seriesname, &status);
02005
02006 if (status == DRMS_ERROR_QUERYFAILED)
02007 {
02008 const char *emsg = DB_GetErrmsg(drms_env->session->db_handle);
02009
02010 if (emsg)
02011 {
02012 JSONDIE((char *)emsg);
02013 }
02014 else
02015 {
02016 JSONDIE("problem with database query");
02017 }
02018 }
02019 else if (status)
02020 JSONDIE("series not found");
02021
02022 jroot = json_new_object();
02023 list_series_info(drms_env, rec, jroot, followLinks, useFitsKeyNames);
02024 if (get_series_stats(rec, jroot) == DRMS_ERROR_QUERYFAILED)
02025 {
02026 const char *emsg = DB_GetErrmsg(drms_env->session->db_handle);
02027
02028 if (emsg)
02029 {
02030 JSONDIE((char *)emsg);
02031 }
02032 else
02033 {
02034 JSONDIE("problem with database query");
02035 }
02036 }
02037
02038 if (!skipRunTime)
02039 {
02040 json_insert_runtime(jroot, StartTime);
02041 }
02042 json_insert_pair_into_object(jroot, "status", json_new_number("0"));
02043 json_tree_to_string(jroot, &jsonOut);
02044 final_json = json_format_string(jsonOut);
02045 free(jsonOut);
02046
02047 printf("Content-type: application/json\n\n");
02048 printf("%s\n",final_json);
02049 free(final_json);
02050 fflush(stdout);
02051 free(seriesname);
02052 manage_userhandle(0, userhandle);
02053
02054 return(0);
02055 }
02056
02057
02058 if (strcmp(op,"rs_summary") == 0)
02059 {
02060 json_t *jroot = json_new_object();
02061 int count=0, status=0;
02062 int countlimit = abs(max_recs);
02063 char val[100];
02064
02065 char *bracket = index(in, '{');
02066 if (bracket)
02067 *bracket = '\0';
02068 if (countlimit)
02069 {
02070 DRMS_RecordSet_t *recordset = drms_open_nrecords (drms_env, in, max_recs, &status);
02071
02072 if (status == DRMS_ERROR_QUERYFAILED)
02073 {
02074 const char *emsg = DB_GetErrmsg(drms_env->session->db_handle);
02075
02076 if (emsg)
02077 {
02078 JSONDIE((char *)emsg);
02079 }
02080 else
02081 {
02082 JSONDIE("problem with database query");
02083 }
02084 }
02085
02086 if (recordset)
02087 {
02088 count = recordset->n;
02089 }
02090 else
02091 {
02092 drms_close_records(recordset, DRMS_FREE_RECORD);
02093 JSONDIE("unable to open records");
02094 }
02095
02096 drms_close_records(recordset, DRMS_FREE_RECORD);
02097 }
02098 else
02099 count = drms_count_records(drms_env, (char *)in, &status);
02100 if (bracket)
02101 *bracket = '{';
02102 if (status == DRMS_ERROR_QUERYFAILED)
02103 {
02104 const char *emsg = DB_GetErrmsg(drms_env->session->db_handle);
02105
02106 if (emsg)
02107 {
02108 JSONDIE((char *)emsg);
02109 }
02110 else
02111 {
02112 JSONDIE("problem with database query");
02113 }
02114 }
02115 else if (status)
02116 JSONDIE("series not found");
02117
02118
02119 sprintf(val, "%d", count);
02120 json_insert_pair_into_object(jroot, "count", json_new_number(val));
02121 if (!skipRunTime)
02122 {
02123 json_insert_runtime(jroot, StartTime);
02124 }
02125 json_insert_pair_into_object(jroot, "status", json_new_number("0"));
02126 json_tree_to_string(jroot, &jsonOut);
02127 final_json = json_format_string(jsonOut);
02128 free(jsonOut);
02129
02130 printf("Content-type: application/json\n\n");
02131 printf("%s\n",final_json);
02132 free(final_json);
02133 fflush(stdout);
02134 report_summary(Server, StartTime, Remote_Address, op, in, max_recs, 0);
02135 manage_userhandle(0, userhandle);
02136 return(0);
02137 }
02138
02139
02140 if (strcmp(op,"rs_list") == 0)
02141 {
02142 int wantRecInfo = cmdparams_get_int(&cmdparams, "R", NULL);
02143 DRMS_RecordSet_t *recordset;
02144 DRMS_Record_t *rec, *template;
02145 DRMS_RecChunking_t cstat = kRecChunking_None;
02146 char seriesname[DRMS_MAXQUERYLEN];
02147 char *keys[1000];
02148 char *segs[1000];
02149 char *links[1000];
02150 int ikey, nkeys = 0;
02151 int iseg, nsegs = 0;
02152 int ilink, nlinks = 0;
02153 char count[100];
02154 json_t *jroot, **keyvals = NULL, **segvals = NULL, **segdims = NULL, **linkvals = NULL, *recinfo = NULL;
02155 json_t **segcparms = NULL;
02156 json_t **segbzeros = NULL;
02157 json_t **segbscales = NULL;
02158 int status=0;
02159 int irec, nrecs;
02160 int record_set_staged = 0;
02161 char *lbracket;
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174 int sumInfoStr = 0;
02175 jroot = json_new_object();
02176 DRMS_Record_t *jsdTemplate = NULL;
02177 DRMS_Segment_t *segTemplate = NULL;
02178 DRMS_Keyword_t *keyTemplate = NULL;
02179 DRMS_Link_t *linkTemplate = NULL;
02180 HIterator_t *last = NULL;
02181 const char *keyNameOut = NULL;
02182 const char *valOut = NULL;
02183 char fitsName[16];
02184 char *fitsValue = NULL;
02185 json_t *keyObj = NULL;
02186 int badKey = 0;
02187 int badSeg = 0;
02188 int badLink = 0;
02189 ListNode_t *lnKey = NULL;
02190 ListNode_t *lnSeg = NULL;
02191 ListNode_t *lnLink = NULL;
02192
02193
02194 strcpy(seriesname, in);
02195 lbracket = index(seriesname, '[');
02196 if (lbracket) *lbracket = '\0';
02197 template = drms_template_record(drms_env, seriesname, &status);
02198 if (status == DRMS_ERROR_QUERYFAILED)
02199 {
02200 const char *emsg = DB_GetErrmsg(drms_env->session->db_handle);
02201
02202 if (emsg)
02203 {
02204 JSONDIE((char *)emsg);
02205 }
02206 else
02207 {
02208 JSONDIE("problem with database query");
02209 }
02210 }
02211 else if (status)
02212 JSONDIE(" jsoc_info: series not found.");
02213
02214
02215 if (max_recs == 0)
02216
02217
02218
02219 recordset = drms_open_records (drms_env, in, &status);
02220 else
02221 recordset = drms_open_nrecords (drms_env, in, max_recs, &status);
02222
02223 if (status == DRMS_ERROR_QUERYFAILED)
02224 {
02225 const char *emsg = DB_GetErrmsg(drms_env->session->db_handle);
02226
02227 if (emsg)
02228 {
02229 JSONDIE((char *)emsg);
02230 }
02231 else
02232 {
02233 JSONDIE("problem with database query");
02234 }
02235 }
02236
02237 if (!recordset)
02238 JSONDIE(" jsoc_info: series not found.");
02239 nrecs = recordset->n;
02240 if (nrecs == 0)
02241 {
02242 json_insert_pair_into_object(jroot, "count", json_new_number("0"));
02243 if (!skipRunTime)
02244 {
02245 json_insert_runtime(jroot, StartTime);
02246 }
02247 json_insert_pair_into_object(jroot, "status", json_new_number("0"));
02248 json_tree_to_string(jroot, &jsonOut);
02249 printf("Content-type: application/json\n\n");
02250 printf("%s\n",jsonOut);
02251 free(jsonOut);
02252 fflush(stdout);
02253 manage_userhandle(0, userhandle);
02254 return(0);
02255 }
02256
02257 struct requisitionStructT requisition = { 0 };
02258
02259 if (useFitsKeyNames && wantRecInfo)
02260 {
02261
02262
02263 requisition.requireSUMinfo = 1;
02264 }
02265
02266
02267
02268 nsegs = 0;
02269 reqSegs = list_llcreate(sizeof(DRMS_Segment_t *), NULL);
02270 if (!reqSegs)
02271 {
02272 JSONDIE("Out of memory.");
02273 }
02274
02275 if (segs_listed)
02276 {
02277
02278
02279 char *thisseg;
02280 CGI_unescape_url(seglist);
02281
02282 if (useFitsKeyNames)
02283 {
02284 nsegs = populateSegList(seglist, followLinks, template, recordset, &record_set_staged, &requisition, reqSegs);
02285 }
02286 else
02287 {
02288 for (thisseg=strtok(seglist, ","); thisseg; thisseg=strtok(NULL,","))
02289 {
02290 if (strcmp(thisseg,"**NONE**")==0)
02291 {
02292 nsegs = 0;
02293 break;
02294 }
02295 if (strcmp(thisseg, "**ALL**")==0)
02296 {
02297 DRMS_Segment_t *seg;
02298 DRMS_Segment_t *oseg = NULL;
02299
02300 while ((seg = drms_record_nextseg(template, &last, 0)))
02301 {
02302 oseg = seg;
02303
02304 if (followLinks && seg->info->islink)
02305 {
02306
02307
02308 int lnkstat = DRMS_SUCCESS;
02309
02310 seg = drms_template_segment_followlink(seg, &lnkstat);
02311 if (lnkstat)
02312 {
02313 continue;
02314 }
02315 }
02316
02317
02318 segs[nsegs++] = strdup (oseg->info->name);
02319 }
02320
02321 if (last)
02322 {
02323 hiter_destroy(&last);
02324 }
02325 }
02326 else
02327 segs[nsegs++] = strdup(thisseg);
02328 }
02329 }
02330 }
02331 free (seglist);
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343 nkeys = 0;
02344 reqKeys = list_llcreate(sizeof(DRMS_Keyword_t *), NULL);
02345 if (!reqKeys)
02346 {
02347 JSONDIE("Out of memory.");
02348 }
02349
02350 if (keys_listed)
02351 {
02352
02353
02354
02355 char *thiskey = NULL;
02356 CGI_unescape_url(keylist);
02357 ListNode_t *node = NULL;
02358
02359 if (useFitsKeyNames)
02360 {
02361 nkeys = populateKeyList(keylist, reqSegs, template, &jsdTemplate, recordset, &record_set_staged, &requisition, reqKeys);
02362 }
02363 else
02364 {
02365 for (thiskey=strtok(keylist, ","); thiskey; thiskey=strtok(NULL,","))
02366 {
02367 if (strcmp(thiskey,"**NONE**")==0)
02368 {
02369 nkeys = 0;
02370 break;
02371 }
02372
02373 if (strcmp(thiskey, "**ALL**")==0)
02374 {
02375 DRMS_Keyword_t *key;
02376
02377 while ((key = drms_record_nextkey(template, &last, 0)))
02378 {
02379 if (!drms_keyword_getimplicit(key))
02380 {
02381 keys[nkeys++] = strdup (key->info->name);
02382 }
02383 }
02384
02385 if (last)
02386 {
02387 hiter_destroy(&last);
02388 }
02389 }
02390 else
02391 keys[nkeys++] = strdup(thiskey);
02392
02393 if (strcmp(thiskey, "*size*") == 0 ||
02394 strcmp(thiskey, "*online*") == 0 ||
02395 strcmp(thiskey, "*retain*") == 0 ||
02396 strcmp(thiskey, "*archive*") == 0)
02397 {
02398 requisition.requireSUMinfo = 1;
02399 }
02400 }
02401 }
02402 }
02403 free (keylist);
02404
02405
02406 nlinks = 0;
02407 reqLinks = list_llcreate(sizeof(DRMS_Link_t *), NULL);
02408 if (!reqLinks)
02409 {
02410 JSONDIE("Out of memory.");
02411 }
02412
02413 if (links_listed)
02414 {
02415
02416 char *thislink;
02417 CGI_unescape_url(linklist);
02418
02419 if (useFitsKeyNames)
02420 {
02421 nlinks = populateLinkList(linklist, template, reqLinks);
02422 }
02423 else
02424 {
02425 for (thislink=strtok(linklist, ","); thislink; thislink=strtok(NULL,","))
02426 {
02427 if (strcmp(thislink,"**NONE**")==0)
02428 {
02429 nlinks = 0;
02430 break;
02431 }
02432
02433 if (strcmp(thislink, "**ALL**")==0)
02434 {
02435 DRMS_Link_t *link;
02436
02437 while ((link = drms_record_nextlink(template, &last)))
02438 links[nlinks++] = strdup (link->info->name);
02439
02440 if (last)
02441 {
02442 hiter_destroy(&last);
02443 }
02444 }
02445 else
02446 {
02447 links[nlinks++] = strdup(thislink);
02448 }
02449 }
02450 }
02451 }
02452 free (linklist);
02453
02454 if (!useFitsKeyNames)
02455 {
02456
02457 if (nkeys)
02458 keyvals = (json_t **)malloc(nkeys * sizeof(json_t *));
02459 for (ikey=0; ikey<nkeys; ikey++)
02460 {
02461 json_t *val = json_new_array();
02462 keyvals[ikey] = val;
02463 }
02464
02465
02466 if (nsegs)
02467 {
02468 segvals = (json_t **)malloc(nsegs * sizeof(json_t *));
02469 segdims = (json_t **)malloc(nsegs * sizeof(json_t *));
02470 segcparms = (json_t **)malloc(nsegs * sizeof(json_t *));
02471 segbzeros = (json_t **)malloc(nsegs * sizeof(json_t *));
02472 segbscales = (json_t **)malloc(nsegs * sizeof(json_t *));
02473 }
02474 for (iseg=0; iseg<nsegs; iseg++)
02475 {
02476 json_t *val = json_new_array();
02477 segvals[iseg] = val;
02478 val = json_new_array();
02479 segdims[iseg] = val;
02480 val = json_new_array();
02481 segcparms[iseg] = val;
02482 val = json_new_array();
02483 segbzeros[iseg] = val;
02484 val = json_new_array();
02485 segbscales[iseg] = val;
02486 }
02487
02488
02489 if (nlinks)
02490 linkvals = (json_t **)malloc(nlinks * sizeof(json_t *));
02491 for (ilink=0; ilink<nlinks; ilink++)
02492 {
02493 json_t *val = json_new_array();
02494 linkvals[ilink] = val;
02495 }
02496 }
02497
02498
02499 if (requisition.requireSUMinfo)
02500 {
02501 drms_record_getinfo(recordset);
02502 }
02503
02504 recArray = json_new_array();
02505 JSOC_INFO_ASSERT(recArray, "out of memory");
02506
02507 int missingKeyName = 0;
02508
02509
02510 for (irec = 0; irec < nrecs; irec++)
02511 {
02512 char recquery[DRMS_MAXQUERYLEN];
02513 char numStr[64];
02514 char *jsonquery;
02515 json_t *recobj = json_new_object();
02516 JSOC_INFO_ASSERT(recobj, "out of memory");
02517
02518 if (max_recs == 0)
02519 rec = drms_recordset_fetchnext(drms_env, recordset, &status, &cstat, NULL);
02520 else
02521 {
02522 rec = recordset->records[irec];
02523 status = DRMS_SUCCESS;
02524 }
02525
02526 json_t *jsonVal = NULL;
02527
02528
02529 if (useFitsKeyNames)
02530 {
02531 json_t *keywordArray = NULL;
02532
02533
02534 drms_sprint_rec_query(recquery, rec);
02535 jsonVal = createJsonStringVal(recquery);
02536 json_insert_pair_into_object(recobj, "specification", jsonVal);
02537 jsonVal = NULL;
02538
02539 if (requisition.requireRecnum)
02540 {
02541 snprintf(numStr, sizeof(numStr), "%lld", rec->recnum);
02542 jsonVal = json_new_number(numStr);
02543 JSOC_INFO_ASSERT(jsonVal, "out of memory");
02544 json_insert_pair_into_object(recobj, "recnum", jsonVal);
02545 jsonVal = NULL;
02546 }
02547
02548 if (requisition.requireSunum)
02549 {
02550 snprintf(numStr, sizeof(numStr), "%lld", rec->sunum);
02551 jsonVal = json_new_number(numStr);
02552 JSOC_INFO_ASSERT(jsonVal, "out of memory");
02553 json_insert_pair_into_object(recobj, "sunum", jsonVal);
02554 jsonVal = NULL;
02555 }
02556
02557 if (requisition.requireSUMinfoSize)
02558 {
02559 if (!rec->suinfo)
02560 {
02561 jsonVal = createJsonStringVal("NA");
02562 }
02563 else
02564 {
02565 snprintf(numStr, sizeof(numStr), "%.0f", rec->suinfo->bytes);
02566 jsonVal = json_new_number(numStr);
02567 JSOC_INFO_ASSERT(jsonVal, "out of memory");
02568 }
02569
02570 json_insert_pair_into_object(recobj, "size", jsonVal);
02571 jsonVal = NULL;
02572 }
02573
02574 if (requisition.requireSUMinfoOnline)
02575 {
02576 if (!rec->suinfo)
02577 {
02578 jsonVal = createJsonStringVal("NA");
02579 }
02580 else
02581 {
02582 jsonVal = createJsonStringVal(rec->suinfo->online_status);
02583 }
02584
02585 json_insert_pair_into_object(recobj, "online", jsonVal);
02586 jsonVal = NULL;
02587 }
02588
02589 if (requisition.requireSUMinfoRetain)
02590 {
02591 if (!rec->suinfo)
02592 {
02593 jsonVal = createJsonStringVal("NA");
02594 }
02595 else
02596 {
02597 int year;
02598 int month;
02599 int day;
02600 char dateStr[64];
02601
02602 if (strcmp("N", rec->suinfo->online_status) == 0)
02603 {
02604 jsonVal = createJsonStringVal("NA");
02605 }
02606 else
02607 {
02608 sscanf(rec->suinfo->effective_date, "%4d%2d%2d", &year, &month, &day);
02609 snprintf(dateStr, sizeof(dateStr), "%4d.%02d.%02d", year, month, day);
02610 jsonVal = createJsonStringVal(dateStr);
02611 }
02612 }
02613
02614 json_insert_pair_into_object(recobj, "expdate", jsonVal);
02615 jsonVal = NULL;
02616 }
02617
02618 if (requisition.requireSUMinfoArchive)
02619 {
02620 if (!rec->suinfo)
02621 {
02622 jsonVal = createJsonStringVal("NA");
02623 }
02624 else
02625 {
02626 if (rec->suinfo->pa_status == DAAP && rec->suinfo->pa_substatus == DAADP)
02627 {
02628 jsonVal = createJsonStringVal("Pending");
02629 }
02630 else
02631 {
02632 jsonVal = createJsonStringVal(rec->suinfo->archive_status);
02633 }
02634 }
02635
02636 json_insert_pair_into_object(recobj, "archive", jsonVal);
02637 jsonVal = NULL;
02638 }
02639
02640 if (requisition.requireRecdir)
02641 {
02642 char recPath[DRMS_MAXPATHLEN];
02643
02644 drms_record_directory(rec, recPath, 0);
02645 jsonVal = createJsonStringVal(recPath);
02646 json_insert_pair_into_object(recobj, "recdir", jsonVal);
02647 jsonVal = NULL;
02648 }
02649
02650 if (requisition.requireDirmtime)
02651 {
02652
02653 struct stat buf;
02654 char recPath[DRMS_MAXPATHLEN];
02655 char timebuf[128];
02656
02657 drms_record_directory(rec, recPath, 0);
02658 stat(recPath, &buf);
02659 sprint_ut(timebuf, buf.st_mtime + UNIX_EPOCH);
02660 jsonVal = createJsonStringVal(timebuf);
02661 json_insert_pair_into_object(recobj, "dirmtime", jsonVal);
02662 jsonVal = NULL;
02663 }
02664
02665 if (requisition.requireLogdir)
02666 {
02667 char *logdir = drms_record_getlogdir(rec);
02668
02669 if (logdir)
02670 {
02671 jsonVal = createJsonStringVal(logdir);
02672 }
02673 else
02674 {
02675 jsonVal = createJsonStringVal("NO LOG");
02676 }
02677
02678 json_insert_pair_into_object(recobj, "logdir", jsonVal);
02679 jsonVal = NULL;
02680 }
02681
02682 keywordArray = json_new_array();
02683
02684
02685 JSOC_INFO_ASSERT(keywordArray, "out of memory");
02686 json_insert_pair_into_object(recobj, "keywords", keywordArray);
02687
02688 list_llreset(reqKeys);
02689 while ((lnKey = list_llnext(reqKeys)) != NULL)
02690 {
02691 keyTemplate = *((DRMS_Keyword_t **)(lnKey->data));
02692 keyNameOut = NULL;
02693 valOut = NULL;
02694 badKey = 0;
02695 missingKeyName = 0;
02696
02697 if (isInvalidKey(keyTemplate))
02698 {
02699 badKey = 1;
02700
02701 if (keyTemplate && keyTemplate->info && *((char *)(keyTemplate->info)) != '\0')
02702 {
02703 keyNameOut = (char *)(keyTemplate->info);
02704 }
02705 else
02706 {
02707 missingKeyName = 1;
02708 }
02709 }
02710 else
02711 {
02712
02713 if (!drms_keyword_getperseg(keyTemplate))
02714 {
02715 DRMS_Keyword_t *keyWithVal = NULL;
02716
02717
02718 if (fitsexport_getmappedextkeyname(keyTemplate, NULL, NULL, fitsName, sizeof(fitsName)) && *fitsName != '\0')
02719 {
02720 keyNameOut = fitsName;
02721 }
02722 else
02723 {
02724 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", keyTemplate->info->name);
02725 missingKeyName = 1;
02726 }
02727
02728
02729
02730 keyWithVal = drms_keyword_lookup(rec, keyTemplate->info->name, 1);
02731
02732 if (keyWithVal)
02733 {
02734
02735
02736
02737 JSOC_INFO_ASSERT(fitsValue == NULL, "about to leak");
02738 fitsexport_getmappedextkeyvalue(keyWithVal, &fitsValue);
02739
02740 if (fitsValue)
02741 {
02742 valOut = fitsValue;
02743 }
02744 else
02745 {
02746 valOut = MISSING_KEY_VALUE;
02747 }
02748 }
02749 else
02750 {
02751
02752
02753
02754 valOut = MISSING_KEY_VALUE;
02755 }
02756 }
02757 else
02758 {
02759
02760 }
02761 }
02762
02763 if (keyNameOut || missingKeyName)
02764 {
02765
02766
02767
02768 keyObj = json_new_object();
02769 JSOC_INFO_ASSERT(keyObj, "out of memory");
02770
02771 if (missingKeyName)
02772 {
02773 snprintf(missingKeyNameBuf, sizeof(missingKeyNameBuf), "%s%02d", MISSING_KEY_NAME, missingKeyNumber++);
02774 jsonVal = createJsonStringVal(missingKeyNameBuf);
02775 }
02776 else
02777 {
02778 jsonVal = createJsonStringVal(keyNameOut);
02779 }
02780 json_insert_pair_into_object(keyObj, "name", jsonVal);
02781 jsonVal = NULL;
02782
02783 if (valOut)
02784 {
02785 jsonVal = createJsonStringVal(valOut);
02786 json_insert_pair_into_object(keyObj, "value", jsonVal);
02787 jsonVal = NULL;
02788 }
02789
02790 if (badKey)
02791 {
02792 jsonVal = json_new_true();
02793 JSOC_INFO_ASSERT(jsonVal, "out of memory");
02794 json_insert_pair_into_object(keyObj, INVALID, jsonVal);
02795 jsonVal = NULL;
02796 }
02797
02798 json_insert_child(keywordArray, keyObj);
02799 }
02800
02801 if (fitsValue)
02802 {
02803 free(fitsValue);
02804 fitsValue = NULL;
02805 }
02806 }
02807 }
02808 else
02809 {
02810
02811 if (wantRecInfo)
02812 {
02813 drms_sprint_rec_query(recquery,rec);
02814 jsonquery = string_to_json(recquery);
02815 json_insert_pair_into_object(recobj, "name", json_new_string(jsonquery));
02816 free(jsonquery);
02817 }
02818
02819 for (ikey=0; ikey<nkeys; ikey++)
02820 {
02821 DRMS_Keyword_t *rec_key_ikey;
02822 json_t *thiskeyval = keyvals[ikey];
02823 json_t *val;
02824 char rawval[20000];
02825 char *jsonval;
02826
02827 if (strcmp(keys[ikey],"*recnum*") == 0)
02828 {
02829 sprintf(rawval,"%lld",rec->recnum);
02830 val = json_new_number(rawval);
02831 }
02832 else if (strcmp(keys[ikey],"*sunum*") == 0)
02833 {
02834 sprintf(rawval,"%lld",rec->sunum);
02835 val = json_new_number(rawval);
02836 }
02837 else if (strcmp(keys[ikey],"*size*") == 0)
02838 {
02839 char size[40];
02840 SUM_info_t *sinfo = rec->suinfo;
02841 if (!sinfo)
02842 val = json_new_string("NA");
02843 else
02844 {
02845 sprintf(size,"%.0f", sinfo->bytes);
02846 val = json_new_string(size);
02847 }
02848 }
02849 else if (strcmp(keys[ikey],"*online*") == 0)
02850 {
02851 SUM_info_t *sinfo = rec->suinfo;
02852 if (!sinfo)
02853 val = json_new_string("NA");
02854 else
02855 val = json_new_string(sinfo->online_status);
02856 }
02857 else if (strcmp(keys[ikey],"*retain*") == 0)
02858 {
02859 SUM_info_t *sinfo = rec->suinfo;
02860 if (!sinfo)
02861 val = json_new_string("NA");
02862 else
02863 {
02864 int y,m,d;
02865 char retain[20];
02866 if (strcmp("N", sinfo->online_status) == 0)
02867 val = json_new_string("N/A");
02868 else
02869 {
02870 sscanf(sinfo->effective_date, "%4d%2d%2d", &y,&m,&d);
02871 sprintf(retain, "%4d.%02d.%02d",y,m,d);
02872 val = json_new_string(retain);
02873 }
02874 }
02875 }
02876 else if (strcmp(keys[ikey],"*archive*") == 0)
02877 {
02878 SUM_info_t *sinfo = rec->suinfo;
02879 if (!sinfo)
02880 val = json_new_string("NA");
02881 else
02882 {
02883 if(sinfo->pa_status == DAAP && sinfo->pa_substatus == DAADP)
02884 val = json_new_string("Pending");
02885 else
02886 val = json_new_string(sinfo->archive_status);
02887 }
02888 }
02889 else if (strcmp(keys[ikey], "*recdir*") == 0)
02890 {
02891 char path[DRMS_MAXPATHLEN];
02892 if (!record_set_staged)
02893 {
02894 drms_stage_records(recordset, 0, 0);
02895 record_set_staged = 1;
02896 }
02897 drms_record_directory (rec, path, 0);
02898 jsonval = string_to_json(path);
02899 val = json_new_string(jsonval);
02900 free(jsonval);
02901 }
02902 else if (strcmp(keys[ikey], "*dirmtime*") == 0)
02903 {
02904 struct stat buf;
02905 char path[DRMS_MAXPATHLEN];
02906 char timebuf[100];
02907 if (!record_set_staged)
02908 {
02909 drms_stage_records(recordset, 0, 0);
02910 record_set_staged = 1;
02911 }
02912 drms_record_directory (rec, path, 0);
02913 stat(path, &buf);
02914 sprint_ut(timebuf, buf.st_mtime + UNIX_EPOCH);
02915 jsonval = string_to_json(timebuf);
02916 val = json_new_string(jsonval);
02917 free(jsonval);
02918 }
02919 else if (strcmp(keys[ikey], "*logdir*") == 0)
02920 {
02921 char *logdir = drms_record_getlogdir(rec);
02922 if (logdir)
02923 {
02924 jsonval = string_to_json(logdir);
02925 free(logdir);
02926 }
02927 else
02928 jsonval = string_to_json("NO LOG");
02929 val = json_new_string(jsonval);
02930 free(jsonval);
02931 }
02932 else
02933 {
02934 rec_key_ikey = drms_keyword_lookup (rec, keys[ikey], 1);
02935 if (!rec_key_ikey)
02936 {
02937 fprintf(stderr,"jsoc_info error, keyword not in series: %s\n",keys[ikey]);
02938
02939 jsonval = string_to_json("Invalid KeyLink");
02940 }
02941 else if (drms_ismissing_keyval(rec_key_ikey) && strcmp(keys[ikey],"QUALITY") != 0)
02942 jsonval = string_to_json("MISSING");
02943 else
02944 {
02945 drms_keyword_snprintfval(rec_key_ikey, rawval, sizeof(rawval));
02946
02947 jsonval = string_to_json(rawval);
02948 }
02949 val = json_new_string(jsonval);
02950 free(jsonval);
02951 }
02952 json_insert_child(thiskeyval, val);
02953 }
02954 }
02955
02956 int online = 0;
02957
02958
02959
02960 if (useFitsKeyNames)
02961 {
02962 json_t *segmentArray = NULL;
02963 json_t *keywordArray = NULL;
02964 char *pch = NULL;
02965 json_t *segObj = NULL;
02966 DRMS_Segment_t *segTemplate = NULL;
02967 DRMS_Segment_t *seg = NULL;
02968 DRMS_Keyword_t *key = NULL;
02969 int segNum = 0;
02970 char recordDir[PATH_MAX];
02971 char path[PATH_MAX];
02972 char dims[128];
02973 int iaxis = 0;
02974 char keyName[DRMS_MAXKEYNAMELEN];
02975 DRMS_Keyword_t *anckey = NULL;
02976 int missingSegName = 0;
02977
02978 segmentArray = json_new_array();
02979
02980 JSOC_INFO_ASSERT(segmentArray, "out of memory");
02981 json_insert_pair_into_object(recobj, "segments", segmentArray);
02982
02983 list_llreset(reqSegs);
02984 while ((lnSeg = list_llnext(reqSegs)) != NULL)
02985 {
02986 badSeg = 0;
02987 segTemplate = *((DRMS_Segment_t **)(lnSeg->data));
02988
02989 segObj = json_new_object();
02990 JSOC_INFO_ASSERT(segObj, "out of memory");
02991
02992 if (isInvalidSeg(segTemplate))
02993 {
02994 badSeg = 1;
02995
02996
02997 if (segTemplate && segTemplate->info && *((char *)(segTemplate->info)) != '\0')
02998 {
02999 jsonVal = createJsonStringVal((char *)(segTemplate->info));
03000 }
03001 else
03002 {
03003 snprintf(missingSegNameBuf, sizeof(missingSegNameBuf), "%s%02d", MISSING_SEG_NAME, missingSegNumber++);
03004 jsonVal = createJsonStringVal(missingSegNameBuf);
03005 }
03006
03007 json_insert_pair_into_object(segObj, "name", jsonVal);
03008 jsonVal = NULL;
03009
03010 jsonVal = json_new_true();
03011 JSOC_INFO_ASSERT(jsonVal, "out of memory");
03012 json_insert_pair_into_object(segObj, INVALID, jsonVal);
03013 jsonVal = NULL;
03014 }
03015 else
03016 {
03017 segNum = segTemplate->info->segnum;
03018
03019
03020 seg = drms_segment_lookup(rec, segTemplate->info->name);
03021
03022
03023 jsonVal = createJsonStringVal(segTemplate->info->name);
03024 json_insert_pair_into_object(segObj, "name", jsonVal);
03025 jsonVal = NULL;
03026
03027 if (seg)
03028 {
03029
03030
03031
03032 drms_record_directory(rec, recordDir, 0);
03033 if (!*recordDir)
03034 {
03035 snprintf(path, sizeof(path), "NoDataDirectory");
03036 }
03037 else
03038 {
03039 snprintf(path, sizeof(path), "%s/%s", dirname(recordDir), seg->filename);
03040 }
03041
03042
03043 if ((strcmp("Y", rec->suinfo->online_status) == 0) && (*path != '\0'))
03044 {
03045 jsonVal = json_new_number("1");
03046 json_insert_pair_into_object(segObj, "online", jsonVal);
03047 jsonVal = NULL;
03048 }
03049 else
03050 {
03051 jsonVal = json_new_number("0");
03052 json_insert_pair_into_object(segObj, "online", jsonVal);
03053 jsonVal = NULL;
03054 }
03055
03056 jsonVal = createJsonStringVal(path);
03057 json_insert_pair_into_object(segObj, "path", jsonVal);
03058 jsonVal = NULL;
03059
03060
03061 dims[0] = '\0';
03062 for (iaxis = 0; iaxis < seg->info->naxis; iaxis++)
03063 {
03064 if (iaxis == 0)
03065 {
03066 snprintf(dims, sizeof(dims), "%d", seg->axis[iaxis]);
03067 }
03068 else
03069 {
03070 snprintf(dims, sizeof(dims), "x%d", seg->axis[iaxis]);
03071 }
03072 }
03073
03074 jsonVal = createJsonStringVal(dims);
03075 json_insert_pair_into_object(segObj, "dims", jsonVal);
03076
03077
03078 if (seg->cparms && strlen(seg->cparms))
03079 {
03080 jsonVal = createJsonStringVal(seg->cparms);
03081 json_insert_pair_into_object(segObj, "cparms", jsonVal);
03082 jsonVal = NULL;
03083 }
03084
03085
03086 snprintf(keyName, sizeof(keyName), "%s_bzero", segTemplate->info->name);
03087 anckey = drms_keyword_lookup(rec, keyName, 1);
03088
03089 if (anckey)
03090 {
03091 fitsexport_getmappedextkeyvalue(anckey, &fitsValue);
03092
03093 if (fitsValue)
03094 {
03095 valOut = fitsValue;
03096 }
03097 else
03098 {
03099 valOut = MISSING_KEY_VALUE;
03100 }
03101
03102 jsonVal = createJsonStringVal(valOut);
03103 json_insert_pair_into_object(segObj, "bzero", jsonVal);
03104 jsonVal = NULL;
03105
03106 if (fitsValue)
03107 {
03108 free(fitsValue);
03109 fitsValue = NULL;
03110 }
03111 }
03112
03113
03114 snprintf(keyName, sizeof(keyName), "%s_bscale", segTemplate->info->name);
03115 anckey = drms_keyword_lookup(rec, keyName, 1);
03116
03117 if (anckey)
03118 {
03119 fitsexport_getmappedextkeyvalue(anckey, &fitsValue);
03120
03121 if (fitsValue)
03122 {
03123 valOut = fitsValue;
03124 }
03125 else
03126 {
03127 valOut = MISSING_KEY_VALUE;
03128 }
03129
03130 jsonVal = createJsonStringVal(valOut);
03131 json_insert_pair_into_object(segObj, "bscale", jsonVal);
03132 jsonVal = NULL;
03133
03134 if (fitsValue)
03135 {
03136 free(fitsValue);
03137 fitsValue = NULL;
03138 }
03139 }
03140
03141
03142 list_llreset(reqKeys);
03143 while ((lnKey = list_llnext(reqKeys)) != NULL)
03144 {
03145 keyTemplate = *((DRMS_Keyword_t **)(lnKey->data));
03146 badKey = 0;
03147 keyNameOut = NULL;
03148 valOut = NULL;
03149 missingKeyName = 0;
03150
03151 if (isInvalidKey(keyTemplate))
03152 {
03153
03154 badKey = 1;
03155 }
03156 else
03157 {
03158 if (drms_keyword_getperseg(keyTemplate))
03159 {
03160 DRMS_Keyword_t *keyWithVal = NULL;
03161
03162 if (!keywordArray)
03163 {
03164 keywordArray = json_new_array();
03165
03166
03167 JSOC_INFO_ASSERT(keywordArray, "out of memory");
03168 json_insert_pair_into_object(segObj, "keywords", keywordArray);
03169 }
03170
03171
03172 if (fitsexport_getmappedextkeyname(keyTemplate, NULL, NULL, fitsName, sizeof(fitsName)) && *fitsName != '\0')
03173 {
03174 keyNameOut = fitsName;
03175 }
03176 else
03177 {
03178 fprintf(stderr, "Unable to map DRMS keyword name %s to FITS keyword name.\n", keyTemplate->info->name);
03179 missingKeyName = 1;
03180 }
03181
03182
03183 snprintf(keyName, sizeof(keyName), "%s_%03d", keyTemplate->info->name, segNum);
03184
03185
03186
03187 keyWithVal = drms_keyword_lookup(rec, keyName, 1);
03188
03189 if (keyWithVal)
03190 {
03191 JSOC_INFO_ASSERT(fitsValue == NULL, "about to leak");
03192 fitsexport_getmappedextkeyvalue(keyWithVal, &fitsValue);
03193
03194 if (fitsValue)
03195 {
03196 valOut = fitsValue;
03197 }
03198 else
03199 {
03200 valOut = MISSING_KEY_VALUE;
03201 }
03202 }
03203 else
03204 {
03205
03206 valOut = MISSING_KEY_VALUE;
03207 }
03208 }
03209 }
03210
03211 JSOC_INFO_ASSERT((keyNameOut != NULL && valOut != NULL) || (keyNameOut == NULL && valOut == NULL), "invalid combination");
03212
03213 if (keyNameOut || missingKeyName)
03214 {
03215
03216
03217
03218 keyObj = json_new_object();
03219 JSOC_INFO_ASSERT(keyObj, "out of memory");
03220
03221 if (missingKeyName)
03222 {
03223 snprintf(missingKeyNameBuf, sizeof(missingKeyNameBuf), "%s%02d", MISSING_KEY_NAME, missingKeyNumber++);
03224 jsonVal = createJsonStringVal(missingKeyNameBuf);
03225 }
03226 else
03227 {
03228 jsonVal = createJsonStringVal(keyNameOut);
03229 }
03230 json_insert_pair_into_object(keyObj, "name", jsonVal);
03231 jsonVal = NULL;
03232
03233 if (valOut)
03234 {
03235 jsonVal = createJsonStringVal(valOut);
03236 json_insert_pair_into_object(keyObj, "value", jsonVal);
03237 jsonVal = NULL;
03238 }
03239
03240 if (badKey)
03241 {
03242 jsonVal = json_new_true();
03243 JSOC_INFO_ASSERT(jsonVal, "out of memory");
03244 json_insert_pair_into_object(keyObj, INVALID, jsonVal);
03245 jsonVal = NULL;
03246 }
03247
03248 json_insert_child(keywordArray, keyObj);
03249 }
03250
03251 if (fitsValue)
03252 {
03253 free(fitsValue);
03254 fitsValue = NULL;
03255 }
03256 }
03257 }
03258 else
03259 {
03260
03261 DRMS_Segment_t *testSeg = NULL;
03262
03263
03264 testSeg = hcon_lookup_lower(&rec->segments, segTemplate->info->name);
03265
03266 jsonVal = createJsonStringVal(segTemplate->info->name);
03267 json_insert_pair_into_object(segObj, "name", jsonVal);
03268 jsonVal = NULL;
03269
03270 if (testSeg && testSeg->info->islink)
03271 {
03272 jsonVal = createJsonStringVal("BadSegLink");
03273 json_insert_pair_into_object(segObj, "path", jsonVal);
03274 jsonVal = NULL;
03275 }
03276 else
03277 {
03278
03279 }
03280
03281 jsonVal = json_new_true();
03282 JSOC_INFO_ASSERT(jsonVal, "out of memory");
03283 json_insert_pair_into_object(segObj, INVALID, jsonVal);
03284 jsonVal = NULL;
03285 }
03286 }
03287
03288 json_insert_child(segmentArray, segObj);
03289 }
03290 }
03291 else
03292 {
03293 for (iseg=0; iseg<nsegs; iseg++)
03294 {
03295 DRMS_Segment_t *rec_seg_iseg = drms_segment_lookup (rec, segs[iseg]);
03296 char *jsonpath;
03297 char *jsondims;
03298 char path[DRMS_MAXPATHLEN];
03299 json_t *thissegval = segvals[iseg];
03300 json_t *thissegdim = segdims[iseg];
03301 json_t *thissegcparms = segcparms[iseg];
03302 json_t *thissegbzero = segbzeros[iseg];
03303 json_t *thissegbscale = segbscales[iseg];
03304 if (rec_seg_iseg)
03305 {
03306 int iaxis, naxis = rec_seg_iseg->info->naxis;
03307 char dims[100], dimval[20];
03308
03309
03310 if (!record_set_staged)
03311 {
03312 drms_stage_records(recordset, 0, 0);
03313 record_set_staged = 1;
03314 }
03315 drms_record_directory (rec_seg_iseg->record, path, 0);
03316
03317
03318 if (!*path)
03319 {
03320 strcpy(path, "NoDataDirectory");
03321 }
03322 else
03323 {
03324 strncat(path, "/", DRMS_MAXPATHLEN);
03325 strncat(path, rec_seg_iseg->filename, DRMS_MAXPATHLEN);
03326 }
03327
03328 jsonpath = string_to_json(path);
03329 json_insert_child(thissegval, json_new_string(jsonpath));
03330 free(jsonpath);
03331 online = strncmp(path, "/SUM",4) == 0;
03332
03333
03334 dims[0] = '\0';
03335 for (iaxis=0; iaxis<naxis; iaxis++)
03336 {
03337 if (iaxis)
03338 strcat(dims, "x");
03339 sprintf(dimval,"%d",rec_seg_iseg->axis[iaxis]);
03340 strcat(dims, dimval);
03341 }
03342 jsondims = string_to_json(dims);
03343 json_insert_child(thissegdim, json_new_string(jsondims));
03344 free(jsondims);
03345
03346
03347
03348 char keybuf[DRMS_MAXKEYNAMELEN];
03349 DRMS_Keyword_t *anckey = NULL;
03350 char *jsonkeyval = NULL;
03351
03352
03353 if (strlen(rec_seg_iseg->cparms))
03354 {
03355 jsonkeyval = string_to_json(rec_seg_iseg->cparms);
03356 json_insert_child(thissegcparms, json_new_string(jsonkeyval));
03357 free(jsonkeyval);
03358 }
03359
03360
03361 snprintf(keybuf, sizeof(keybuf), "%s_bzero", segs[iseg]);
03362 anckey = drms_keyword_lookup(rec, keybuf, 1);
03363
03364 if (anckey)
03365 {
03366 drms_keyword_snprintfval(anckey, keybuf, sizeof(keybuf));
03367
03368
03369 jsonkeyval = string_to_json(keybuf);
03370 json_insert_child(thissegbzero, json_new_string(jsonkeyval));
03371 free(jsonkeyval);
03372 }
03373
03374
03375 anckey = NULL;
03376 snprintf(keybuf, sizeof(keybuf), "%s_bscale", segs[iseg]);
03377 anckey = drms_keyword_lookup(rec, keybuf, 1);
03378
03379 if (anckey)
03380 {
03381 drms_keyword_snprintfval(anckey, keybuf, sizeof(keybuf));
03382
03383
03384 jsonkeyval = string_to_json(keybuf);
03385 json_insert_child(thissegbscale, json_new_string(jsonkeyval));
03386 free(jsonkeyval);
03387 }
03388 }
03389 else
03390 {
03391 char *nosegmsg = "InvalidSegName";
03392 DRMS_Segment_t *segment = hcon_lookup_lower(&rec->segments, segs[iseg]);
03393 if (segment && segment->info->islink)
03394 nosegmsg = "BadSegLink";
03395 jsonpath = string_to_json(nosegmsg);
03396 json_insert_child(thissegval, json_new_string(jsonpath));
03397 free(jsonpath);
03398 jsondims = string_to_json("NA");
03399 json_insert_child(thissegdim, json_new_string(jsondims));
03400 free(jsondims);
03401 }
03402 }
03403 }
03404
03405 if (useFitsKeyNames)
03406 {
03407 json_t *linkArray = NULL;
03408 DRMS_Link_t *linkTemplate = NULL;
03409 DRMS_Link_t *link = NULL;
03410 json_t *linkObj = NULL;
03411 DRMS_Record_t *linkedRec = NULL;
03412 char linkSpec[DRMS_MAXQUERYLEN];
03413 int missingLinkName = 0;
03414
03415 linkArray = json_new_array();
03416
03417
03418 JSOC_INFO_ASSERT(linkArray, "out of memory");
03419 json_insert_pair_into_object(recobj, "links", linkArray);
03420
03421 list_llreset(reqLinks);
03422 while ((lnLink = list_llnext(reqLinks)) != NULL)
03423 {
03424 linkTemplate = *((DRMS_Link_t **)(lnLink->data));
03425 badLink = 0;
03426 valOut = NULL;
03427 *linkSpec = '\0';
03428
03429 linkObj = json_new_object();
03430 JSOC_INFO_ASSERT(linkObj, "out of memory");
03431
03432 if (isInvalidLink(linkTemplate))
03433 {
03434 badLink = 1;
03435
03436 if (linkTemplate && linkTemplate->info && *((char *)(linkTemplate->info)) != '\0')
03437 {
03438 valOut = (char *)(linkTemplate->info);
03439 }
03440 else
03441 {
03442 missingLinkName = 1;
03443 }
03444 }
03445 else if (!(linkTemplate->info) || *(linkTemplate->info->name) == '\0')
03446 {
03447 missingLinkName = 1;
03448 badLink = 1;
03449 }
03450 else
03451 {
03452 valOut = linkTemplate->info->name;
03453
03454
03455
03456 link = hcon_lookup_lower(&rec->links, linkTemplate->info->name);
03457
03458 if (!link || !link->info)
03459 {
03460 badLink = 1;
03461 }
03462 else
03463 {
03464 linkedRec = drms_link_follow(rec, linkTemplate->info->name, &status);
03465
03466 if (!linkedRec || !linkedRec->seriesinfo || *(linkedRec->seriesinfo->seriesname) == '\0')
03467 {
03468 badLink = 1;
03469 }
03470 else
03471 {
03472 if (link->info->type == DYNAMIC_LINK)
03473 {
03474 drms_sprint_rec_query(linkSpec, linkedRec);
03475 }
03476 else
03477 {
03478 snprintf(linkSpec, sizeof(linkSpec), "%s[:#%lld]", linkedRec->seriesinfo->seriesname, linkedRec->recnum);
03479 }
03480
03481 drms_close_record(linkedRec, DRMS_FREE_RECORD);
03482 }
03483 }
03484 }
03485
03486 if (missingLinkName)
03487 {
03488 snprintf(missingLinkNameBuf, sizeof(missingLinkNameBuf), "%s%02d", MISSING_LINK_NAME, missingLinkNumber++);
03489 jsonVal = createJsonStringVal(missingLinkNameBuf);
03490 }
03491 else
03492 {
03493 jsonVal = createJsonStringVal(valOut);
03494 }
03495 json_insert_pair_into_object(linkObj, "name", jsonVal);
03496 jsonVal = NULL;
03497
03498 if (*linkSpec != '\0')
03499 {
03500 jsonVal = createJsonStringVal(linkSpec);
03501 json_insert_pair_into_object(linkObj, "linkedrec", jsonVal);
03502 jsonVal = NULL;
03503 }
03504
03505 if (badLink)
03506 {
03507 jsonVal = json_new_true();
03508 JSOC_INFO_ASSERT(jsonVal, "out of memory");
03509 json_insert_pair_into_object(linkObj, INVALID, jsonVal);
03510 jsonVal = NULL;
03511 }
03512
03513 json_insert_child(linkArray, linkObj);
03514 }
03515 }
03516 else
03517 {
03518
03519 for (ilink=0; ilink<nlinks; ilink++)
03520 {
03521 DRMS_Link_t *rec_link = hcon_lookup_lower (&rec->links, links[ilink]);
03522 DRMS_Record_t *linked_rec = drms_link_follow(rec, links[ilink], &status);
03523 char linkquery[DRMS_MAXQUERYLEN];
03524 if (linked_rec)
03525 {
03526 if (rec_link->info->type == DYNAMIC_LINK)
03527 drms_sprint_rec_query(linkquery, linked_rec);
03528 else
03529 sprintf(linkquery, "%s[:#%lld]", linked_rec->seriesinfo->seriesname, linked_rec->recnum);
03530 drms_close_record(linked_rec, DRMS_FREE_RECORD);
03531
03532 json_t *thislinkval = linkvals[ilink];
03533 json_insert_child(thislinkval, json_new_string(linkquery));
03534 }
03535 else
03536 {
03537 json_t *thislinkval = linkvals[ilink];
03538 json_insert_child(thislinkval, json_new_string("Invalid_Link"));
03539 }
03540 }
03541 }
03542
03543 if (useFitsKeyNames)
03544 {
03545 if (wantRecInfo && !requisition.requireSUMinfoOnline)
03546 {
03547 if (!rec->suinfo)
03548 {
03549 jsonVal = createJsonStringVal("NA");
03550 }
03551 else
03552 {
03553 if (strcmp("Y", rec->suinfo->online_status) == 0)
03554 {
03555 jsonVal = json_new_number("1");
03556 }
03557 else
03558 {
03559 jsonVal = json_new_number("0");
03560 }
03561 }
03562
03563 JSOC_INFO_ASSERT(jsonVal, "out of memory");
03564 json_insert_pair_into_object(recobj, "online", jsonVal);
03565 jsonVal = NULL;
03566 }
03567
03568 json_insert_child(recArray, recobj);
03569 }
03570 else
03571 {
03572 if (!recinfo)
03573 {
03574 recinfo = json_new_array();
03575 }
03576
03577
03578 if (wantRecInfo)
03579 {
03580 json_insert_pair_into_object(recobj, "online", json_new_number(online ? "1" : "0"));
03581 json_insert_child(recinfo, recobj);
03582 }
03583 }
03584 }
03585
03586
03587 list_llreset(reqKeys);
03588 while ((lnKey = list_llnext(reqKeys)) != NULL)
03589 {
03590 keyTemplate = *((DRMS_Keyword_t **)(lnKey->data));
03591
03592 if (isInvalidKey(keyTemplate))
03593 {
03594
03595 list_llremove(reqKeys, lnKey);
03596
03597 if (keyTemplate)
03598 {
03599 if (keyTemplate->info)
03600 {
03601 free(keyTemplate->info);
03602 }
03603
03604 free(keyTemplate);
03605 }
03606
03607 list_llfreenode(&lnKey);
03608 }
03609 }
03610
03611 list_llreset(reqSegs);
03612 while ((lnSeg = list_llnext(reqSegs)) != NULL)
03613 {
03614 segTemplate = *((DRMS_Segment_t **)(lnSeg->data));
03615
03616 if (isInvalidSeg(segTemplate))
03617 {
03618
03619 list_llremove(reqSegs, lnSeg);
03620
03621 if (segTemplate)
03622 {
03623 if (segTemplate->info)
03624 {
03625 free(segTemplate->info);
03626 }
03627
03628 free(segTemplate);
03629 }
03630
03631 list_llfreenode(&lnSeg);
03632 }
03633 }
03634
03635 list_llreset(reqLinks);
03636 while ((lnLink = list_llnext(reqLinks)) != NULL)
03637 {
03638 linkTemplate = *((DRMS_Link_t **)(lnLink->data));
03639
03640 if (isInvalidLink(linkTemplate))
03641 {
03642 list_llremove(reqLinks, lnLink);
03643
03644 if (linkTemplate)
03645 {
03646 if (linkTemplate->info)
03647 {
03648 free(linkTemplate->info);
03649 }
03650
03651 free(linkTemplate);
03652 }
03653
03654 list_llfreenode(&lnLink);
03655 }
03656 }
03657
03658
03659 if (useFitsKeyNames)
03660 {
03661 json_insert_pair_into_object(jroot, "recset", recArray);
03662 }
03663 else
03664 {
03665 json_t *json_keywords = json_new_array();
03666 json_t *json_segments = json_new_array();
03667 json_t *json_links = json_new_array();
03668
03669 if (wantRecInfo)
03670 json_insert_pair_into_object(jroot, "recinfo", recinfo);
03671
03672 for (ikey=0; ikey<nkeys; ikey++)
03673 {
03674 json_t *keyname = json_new_string(keys[ikey]);
03675 json_t *keyobj = json_new_object();
03676 json_insert_pair_into_object(keyobj, "name", keyname);
03677 json_insert_pair_into_object(keyobj, "values", keyvals[ikey]);
03678 json_insert_child(json_keywords, keyobj);
03679 }
03680 json_insert_pair_into_object(jroot, "keywords", json_keywords);
03681
03682 for (iseg=0; iseg<nsegs; iseg++)
03683 {
03684 json_t *segname = json_new_string(segs[iseg]);
03685 json_t *segobj = json_new_object();
03686 json_insert_pair_into_object(segobj, "name", segname);
03687 json_insert_pair_into_object(segobj, "values", segvals[iseg]);
03688 json_insert_pair_into_object(segobj, "dims", segdims[iseg]);
03689 json_insert_pair_into_object(segobj, "cparms", segcparms[iseg]);
03690 json_insert_pair_into_object(segobj, "bzeros", segbzeros[iseg]);
03691 json_insert_pair_into_object(segobj, "bscales", segbscales[iseg]);
03692 json_insert_child(json_segments, segobj);
03693 }
03694
03695 json_insert_pair_into_object(jroot, "segments", json_segments);
03696
03697 for (ilink=0; ilink<nlinks; ilink++)
03698 {
03699 json_t *linkname = json_new_string(links[ilink]);
03700 json_t *linkobj = json_new_object();
03701 json_insert_pair_into_object(linkobj, "name", linkname);
03702 json_insert_pair_into_object(linkobj, "values", linkvals[ilink]);
03703 json_insert_child(json_links, linkobj);
03704 }
03705 json_insert_pair_into_object(jroot, "links", json_links);
03706 }
03707
03708 snprintf(count, sizeof(count), "%d", nrecs);
03709 json_insert_pair_into_object(jroot, "count", json_new_number(count));
03710 json_insert_runtime(jroot, StartTime);
03711 json_insert_pair_into_object(jroot, "status", json_new_number("0"));
03712
03713 drms_close_records(recordset, DRMS_FREE_RECORD);
03714 json_tree_to_string(jroot, &final_json);
03715 printf("Content-type: application/json\n\n");
03716 printf("%s\n",final_json);
03717 free(final_json);
03718 fflush(stdout);
03719
03720 json_free_value(&jroot);
03721
03722 if (reqLinks)
03723 {
03724 list_llfree(&reqLinks);
03725 }
03726
03727 if (reqSegs)
03728 {
03729 list_llfree(&reqSegs);
03730 }
03731
03732 if (reqKeys)
03733 {
03734 list_llfree(&reqKeys);
03735 }
03736
03737 drms_destroy_jsdtemplate_record(&jsdTemplate);
03738
03739 report_summary(Server, StartTime, Remote_Address, op, in, max_recs, 0);
03740 manage_userhandle(0, userhandle);
03741 return(0);
03742 }
03743
03744 manage_userhandle(0, userhandle);
03745 return(0);
03746 }
03747