00001
00002 #include "drms.h"
00003 #include "drms_priv.h"
00004 #include "xmem.h"
00005 #include "cfitsio.h"
00006 #include "drms_fitsrw.h"
00007 #include "atoinc.h"
00008 #include "fitsexport.h"
00009
00010 #define kDATEKEYNAME "DATE"
00011
00012
00013 const DRMS_Type_t kIndexKWType = DRMS_TYPE_LONGLONG;
00014 const char *kIndexKWFormat = "%lld";
00015
00016 struct RecScopeStrings_struct
00017 {
00018 DRMS_RecScopeType_t type;
00019 const char *str;
00020 };
00021
00022 typedef struct RecScopeStrings_struct RecScopeStrings_t;
00023
00024 struct SlotKeyUnitStrings_struct
00025 {
00026 DRMS_SlotKeyUnit_t type;
00027 const char *str;
00028 };
00029
00030 typedef struct SlotKeyUnitStrings_struct SlotKeyUnitStrings_t;
00031
00032 static RecScopeStrings_t gSS[] =
00033 {
00034 {kRecScopeType_Variable, "variable"},
00035 {kRecScopeType_Constant, "constant"},
00036 {kRecScopeType_Index, "index"},
00037 {kRecScopeType_TS_EQ, "ts_eq"},
00038 {kRecScopeType_SLOT, "slot"},
00039 {kRecScopeType_ENUM, "enum"},
00040 {kRecScopeType_CARR, "carr"},
00041 {kRecScopeType_TS_SLOT, "ts_slot"},
00042 {(DRMS_RecScopeType_t)-99, ""}
00043 };
00044
00045 static SlotKeyUnitStrings_t gSUS[] =
00046 {
00047 {kSlotKeyUnit_TSeconds, "tenthsecs"},
00048 {kSlotKeyUnit_Seconds, "secs"},
00049 {kSlotKeyUnit_Minutes, "mins"},
00050 {kSlotKeyUnit_Hours, "hours"},
00051 {kSlotKeyUnit_Days, "days"},
00052 {kSlotKeyUnit_Degrees, "degrees"},
00053 {kSlotKeyUnit_Arcminutes, "arcmins"},
00054 {kSlotKeyUnit_Arcseconds, "arcsecs"},
00055 {kSlotKeyUnit_MAS, "milliarcsecs"},
00056 {kSlotKeyUnit_Radians, "rads"},
00057 {kSlotKeyUnit_MicroRadians, "microrads"},
00058 {(DRMS_SlotKeyUnit_t)-99, ""}
00059 };
00060
00061 const double kSlotKeyBase_Carr = 0.0;
00062
00063 static HContainer_t *gRecScopeStrHC = NULL;
00064 static HContainer_t *gRecScopeHC = NULL;
00065 static HContainer_t *gSlotUnitHC = NULL;
00066
00067 const int kMaxRecScopeTypeKey = 4096;
00068 const int kMaxSlotUnitKey = 128;
00069
00070 void drms_keyword_term()
00071 {
00072 if (gRecScopeStrHC)
00073 {
00074 hcon_destroy(&gRecScopeStrHC);
00075 }
00076 if (gRecScopeHC)
00077 {
00078 hcon_destroy(&gRecScopeHC);
00079 }
00080 if (gSlotUnitHC)
00081 {
00082 hcon_destroy(&gSlotUnitHC);
00083 }
00084 }
00085
00086
00087 static DRMS_Keyword_t * __drms_keyword_lookup(DRMS_Record_t *rec,
00088 const char *key, int depth);
00089
00090
00091 void drms_free_template_keyword_struct(DRMS_Keyword_t *key)
00092 {
00093 if (key && key->info)
00094 {
00095 if (key->info->type==DRMS_TYPE_STRING)
00096 free(key->value.string_val);
00097
00098 free(key->info);
00099 }
00100 }
00101
00102 void drms_free_keyword_struct(DRMS_Keyword_t *key)
00103 {
00104 if (key && key->info)
00105 {
00106 if (key->info->type==DRMS_TYPE_STRING)
00107 free(key->value.string_val);
00108 }
00109 }
00110
00111
00112 void drms_copy_keyword_struct(DRMS_Keyword_t *dst, DRMS_Keyword_t *src)
00113 {
00114
00115
00116
00117 if (dst->info==NULL)
00118 dst->info = src->info;
00119 if (src->info->type == DRMS_TYPE_STRING)
00120 {
00121
00122 if (dst->info->type == DRMS_TYPE_STRING && dst->value.string_val != src->value.string_val)
00123 free(dst->value.string_val);
00124
00125
00126 memcpy(dst, src, sizeof(DRMS_Keyword_t));
00127 dst->value.string_val = strdup(src->value.string_val);
00128 }
00129 else
00130 {
00131
00132 memcpy(dst, src, sizeof(DRMS_Keyword_t));
00133 }
00134 }
00135
00136
00137 HContainer_t *drms_create_keyword_prototypes(DRMS_Record_t *target,
00138 DRMS_Record_t *source,
00139 int *status)
00140 {
00141 HContainer_t *ret = NULL;
00142 DRMS_Keyword_t *tKey = NULL;
00143 DRMS_Keyword_t *sKey = NULL;
00144
00145 XASSERT(target != NULL && target->keywords.num_total == 0 && source != NULL);
00146
00147 if (target != NULL && target->keywords.num_total == 0 && source != NULL)
00148 {
00149 *status = DRMS_SUCCESS;
00150 HIterator_t hit;
00151 hiter_new_sort(&hit, &(source->keywords), drms_keyword_ranksort);
00152
00153 while ((sKey = hiter_getnext(&hit)) != NULL)
00154 {
00155 if (sKey->info && strlen(sKey->info->name) > 0)
00156 {
00157 tKey = hcon_allocslot_lower(&(target->keywords), sKey->info->name);
00158 XASSERT(tKey);
00159 memset(tKey, 0, sizeof(DRMS_Keyword_t));
00160 tKey->info = malloc(sizeof(DRMS_KeywordInfo_t));
00161 XASSERT(tKey->info);
00162 memset(tKey->info, 0, sizeof(DRMS_KeywordInfo_t));
00163
00164 if (tKey && tKey->info)
00165 {
00166
00167 tKey->record = target;
00168
00169
00170 memcpy(tKey->info, sKey->info, sizeof(DRMS_KeywordInfo_t));
00171
00172 if (tKey->info->type == DRMS_TYPE_STRING &&
00173 sKey->value.string_val != NULL)
00174 {
00175 copy_string(&(tKey->value.string_val), sKey->value.string_val);
00176 }
00177 else
00178 {
00179 tKey->value = sKey->value;
00180 }
00181 }
00182 else
00183 {
00184 *status = DRMS_ERROR_OUTOFMEMORY;
00185 }
00186 }
00187 else
00188 {
00189 *status = DRMS_ERROR_INVALIDKEYWORD;
00190 }
00191 }
00192
00193 hiter_free(&hit);
00194
00195 if (*status == DRMS_SUCCESS)
00196 {
00197 ret = &(target->keywords);
00198 }
00199 }
00200 else
00201 {
00202 *status = DRMS_ERROR_INVALIDRECORD;
00203 }
00204
00205 return ret;
00206 }
00207
00208 void drms_keyword_print(DRMS_Keyword_t *key)
00209 {
00210 drms_keyword_fprint(stdout, key);
00211 }
00212
00213
00214 void drms_keyword_fprint(FILE *keyfile, DRMS_Keyword_t *key)
00215 {
00216 const int fieldwidth=13;
00217
00218 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "name", key->info->name);
00219 fprintf(keyfile, "\t%-*s:\t%d\n", fieldwidth, "islink", key->info->islink);
00220 if (key->info->islink)
00221 {
00222 fprintf(keyfile, "\t%-*s:\t%s\n", fieldwidth, "linkname", key->info->linkname);
00223 fprintf(keyfile, "\t%-*s:\t%s\n", fieldwidth, "target keyword", key->info->target_key);
00224 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "description", key->info->description);
00225 }
00226 else
00227 {
00228 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "type", drms_type2str(key->info->type));
00229 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "format", key->info->format);
00230 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "unit", key->info->unit);
00231 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "description", key->info->description);
00232 fprintf(keyfile, "\t%-*s:\t%d\n", fieldwidth, "recordscope", (int)key->info->recscope);
00233 fprintf(keyfile, "\t%-*s:\t%d\n", fieldwidth, "per_segment", drms_keyword_getperseg(key));
00234 fprintf(keyfile, "\t%-*s:\t%d\n", fieldwidth, "intprime", drms_keyword_getintprime(key));
00235 fprintf(keyfile, "\t%-*s:\t%d\n", fieldwidth, "extprime", drms_keyword_getextprime(key));
00236 fprintf(keyfile, "\t%-*s:\t",fieldwidth,"value");
00237
00238 drms_keyword_fprintval(keyfile, key);
00239 }
00240
00241 fprintf(keyfile, "\n");
00242 }
00243
00244
00245
00246 void drms_keyword_printval(DRMS_Keyword_t *key)
00247 {
00248 drms_keyword_fprintval(stdout, key);
00249 }
00250
00251 static void PrintTimeVal(DRMS_Keyword_t *key, char *outbuf, int size)
00252 {
00253 char buf[1024];
00254 char *endptr = NULL;
00255 TIME interval = 0;
00256
00257 interval = atoinc(key->info->unit);
00258 if (interval > 0)
00259 {
00260
00261
00262 snprintf(buf, sizeof(buf), key->info->format, key->value.time_val / interval);
00263 }
00264 else
00265 {
00266
00267 int format = (int)strtod(key->info->format, &endptr);
00268 sprint_time(buf, key->value.time_val, key->info->unit, format);
00269 }
00270
00271 if (outbuf)
00272 {
00273 snprintf(outbuf, size, "%s", buf);
00274 }
00275 }
00276
00277
00278 void drms_keyword_fprintval(FILE *keyfile, DRMS_Keyword_t *key)
00279 {
00280 const char *fmt = NULL;
00281
00282 if (key->info->format && *(key->info->format) != '\0')
00283 {
00284 fmt = key->info->format;
00285 }
00286
00287 switch(key->info->type)
00288 {
00289 case DRMS_TYPE_CHAR:
00290 fmt = (fmt != NULL) ? fmt : "%hhd";
00291 fprintf(keyfile, fmt, key->value.char_val);
00292 break;
00293 case DRMS_TYPE_SHORT:
00294 fmt = (fmt != NULL) ? fmt : "%hd";
00295 fprintf(keyfile, fmt, key->value.short_val);
00296 break;
00297 case DRMS_TYPE_INT:
00298 fmt = (fmt != NULL) ? fmt : "%d";
00299 fprintf(keyfile, fmt, key->value.int_val);
00300 break;
00301 case DRMS_TYPE_LONGLONG:
00302 fmt = (fmt != NULL) ? fmt : "%lld";
00303 fprintf(keyfile, fmt, key->value.longlong_val);
00304 break;
00305 case DRMS_TYPE_FLOAT:
00306 fmt = (fmt != NULL) ? fmt : "%f";
00307 fprintf(keyfile, fmt, key->value.float_val);
00308 break;
00309 case DRMS_TYPE_DOUBLE:
00310 fmt = (fmt != NULL) ? fmt : "%f";
00311 fprintf(keyfile, fmt, key->value.double_val);
00312 break;
00313 case DRMS_TYPE_TIME:
00314 {
00315 char buf[1024];
00316 PrintTimeVal(key, buf, sizeof(buf));
00317 fprintf(keyfile, "%s", buf);
00318 }
00319 break;
00320 case DRMS_TYPE_STRING:
00321 fmt = (fmt != NULL) ? fmt : "%s";
00322 fprintf(keyfile, fmt, key->value.string_val);
00323 break;
00324 default:
00325 break;
00326 }
00327 }
00328
00329 void drms_keyword_snprintfval(DRMS_Keyword_t *key, char *buf, int size)
00330 {
00331 const char *fmt = NULL;
00332
00333 if (key->info->format && *(key->info->format) != '\0')
00334 {
00335 fmt = key->info->format;
00336 }
00337
00338 switch(key->info->type)
00339 {
00340 case DRMS_TYPE_CHAR:
00341 fmt = (fmt != NULL) ? fmt : "%hhd";
00342 snprintf(buf, size, fmt, key->value.char_val);
00343 break;
00344 case DRMS_TYPE_SHORT:
00345 fmt = (fmt != NULL) ? fmt : "%hd";
00346 snprintf(buf, size, fmt, key->value.short_val);
00347 break;
00348 case DRMS_TYPE_INT:
00349 fmt = (fmt != NULL) ? fmt : "%d";
00350 snprintf(buf, size, fmt, key->value.int_val);
00351 break;
00352 case DRMS_TYPE_LONGLONG:
00353 fmt = (fmt != NULL) ? fmt : "%lld";
00354 snprintf(buf, size, fmt, key->value.longlong_val);
00355 break;
00356 case DRMS_TYPE_FLOAT:
00357 fmt = (fmt != NULL) ? fmt : "%f";
00358 snprintf(buf, size, fmt, key->value.float_val);
00359 break;
00360 case DRMS_TYPE_DOUBLE:
00361 fmt = (fmt != NULL) ? fmt : "%f";
00362 snprintf(buf, size, fmt, key->value.double_val);
00363 break;
00364 case DRMS_TYPE_TIME:
00365 {
00366 char intbuf[1024];
00367 PrintTimeVal(key, intbuf, sizeof(intbuf));
00368 snprintf(buf, size, "%s", intbuf);
00369 }
00370 break;
00371 case DRMS_TYPE_STRING:
00372 fmt = (fmt != NULL) ? fmt : "%s";
00373 snprintf(buf, size, fmt, key->value.string_val);
00374 break;
00375 default:
00376 break;
00377 }
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 int drms_template_keywords_int(DRMS_Record_t *template, int expandperseg, const char *cols)
00389 {
00390 DRMS_Env_t *env;
00391 int num_segments, per_segment, seg, status;
00392 char name0[DRMS_MAXKEYNAMELEN], name[DRMS_MAXKEYNAMELEN];
00393 char defval[DRMS_DEFVAL_MAXLEN], query[DRMS_MAXQUERYLEN];
00394 DRMS_Keyword_t *key;
00395 int irow;
00396 int rankindeterminate;
00397 int constrank;
00398 DB_Binary_Result_t *qres;
00399
00400 DRMS_SeriesVersion_t vers2_1 = {"2.1", ""};
00401
00402 env = template->env;
00403
00404 hcon_init(&template->keywords, sizeof(DRMS_Keyword_t), DRMS_MAXHASHKEYLEN,
00405 (void (*)(const void *)) drms_free_keyword_struct,
00406 (void (*)(const void *, const void *)) drms_copy_keyword_struct);
00407
00408 num_segments = hcon_size(&template->segments);
00409
00410
00411
00412
00413
00414 int rank;
00415 char *colnames = strdup(cols);
00416 char *pch = NULL;
00417 char *pdel = NULL;
00418
00419
00420 pch = colnames;
00421 char *namespace = ns(template->seriesinfo->seriesname);
00422 char *lcseries = strdup(template->seriesinfo->seriesname);
00423 rank = 0;
00424
00425 if (!lcseries)
00426 {
00427 status = DRMS_ERROR_OUTOFMEMORY;
00428 goto bailout;
00429 }
00430
00431 strtolower(lcseries);
00432
00433
00434 sprintf(query, "select keywordname, islink, linkname, targetkeyw, type, "
00435 "defaultval, format, unit, isconstant, persegment, "
00436 "description from %s.%s where lower(seriesname) = '%s'",
00437 namespace, DRMS_MASTER_KEYWORD_TABLE, lcseries);
00438
00439 if (env->verbose)
00440 {
00441 fprintf(stdout, "Template Keyword Query: %s\n", query);
00442 }
00443
00444 free(lcseries);
00445
00446 if ((qres = drms_query_bin(env->session, query)) == NULL)
00447 {
00448 if (colnames)
00449 {
00450 free(colnames);
00451 }
00452
00453 if (namespace)
00454 {
00455 free(namespace);
00456 }
00457 return DRMS_ERROR_QUERYFAILED;
00458 }
00459
00460 if (qres->num_rows>0 && qres->num_cols != 11 )
00461 {
00462 if (colnames)
00463 {
00464 free(colnames);
00465 }
00466
00467 if (namespace)
00468 {
00469 free(namespace);
00470 }
00471 status = DRMS_ERROR_BADFIELDCOUNT;
00472 goto bailout;
00473 }
00474
00475 rankindeterminate = 0;
00476 constrank = 0;
00477
00478 for (irow = 0; irow < (int)qres->num_rows; irow++)
00479 {
00480 if (expandperseg)
00481 {
00482 per_segment = ((db_binary_field_getint(qres, irow, 9) & kKeywordFlag_PerSegment) != 0);
00483 }
00484 else
00485 {
00486 per_segment = 0;
00487 }
00488
00489 for (seg=0; seg<(per_segment==1?num_segments:1); seg++)
00490 {
00491
00492 db_binary_field_getstr(qres, irow, 0, sizeof(name0), name0);
00493
00494
00495
00496
00497 if (per_segment)
00498 sprintf(name,"%s_%03d",name0,seg);
00499 else
00500 strcpy(name,name0);
00501
00502
00503 key = hcon_allocslot_lower(&template->keywords, name);
00504 memset(key,0,sizeof(DRMS_Keyword_t));
00505
00506 key->record = template;
00507 key->info = malloc(sizeof(DRMS_KeywordInfo_t));
00508 XASSERT(key->info);
00509 memset(key->info,0,sizeof(DRMS_KeywordInfo_t));
00510
00511 strcpy(key->info->name, name);
00512
00513 key->info->islink = db_binary_field_getint(qres, irow, 1);
00514 db_binary_field_getstr(qres, irow, 10, sizeof(key->info->description),key->info->description);
00515 if (!key->info->islink)
00516 {
00517 key->info->linkname[0] = 0;
00518 key->info->target_key[0] = 0;
00519 db_binary_field_getstr(qres, irow, 4, sizeof(name),name);
00520 key->info->type = drms_str2type(name);
00521 db_binary_field_getstr(qres, irow, 5, sizeof(defval), defval);
00522 drms_strval(key->info->type, &key->value, defval);
00523 db_binary_field_getstr(qres, irow, 6, sizeof(key->info->format), key->info->format);
00524 db_binary_field_getstr(qres, irow, 7, sizeof(key->info->unit), key->info->unit);
00525 key->info->recscope = (DRMS_RecScopeType_t)db_binary_field_getint(qres, irow, 8);
00526
00527
00528 if (key->info->type == DRMS_TYPE_TIME)
00529 {
00530
00531
00532
00533 TIME interval = atoinc(key->info->unit);
00534 if (interval > 0)
00535 {
00536 key->value.double_val = atof(defval);
00537 }
00538 }
00539
00540
00541
00542
00543
00544
00545
00546 key->info->kwflags = db_binary_field_getint(qres, irow, 9);
00547
00548
00549
00550
00551 rank = (key->info->kwflags & 0xFFFF0000) >> 16;
00552
00553 if (rank == 0)
00554 {
00555 rankindeterminate = 1;
00556
00557
00558
00559
00560
00561
00562
00563 key->info->rank = constrank++;
00564 }
00565 else
00566 {
00567 key->info->rank = rank - 1;
00568 }
00569
00570
00571
00572
00573
00574 if (!drms_series_isvers(template->seriesinfo, &vers2_1))
00575 {
00576 drms_keyword_unsetintprime(key);
00577 drms_keyword_unsetextprime(key);
00578 }
00579 }
00580 else
00581 {
00582 db_binary_field_getstr(qres, irow, 2, sizeof(key->info->linkname),key->info->linkname);
00583 db_binary_field_getstr(qres, irow, 3, sizeof(key->info->target_key),key->info->target_key);
00584 key->info->type = DRMS_TYPE_INT;
00585 key->value.int_val = 0;
00586 key->info->format[0] = 0;
00587 key->info->unit[0] = 0;
00588 key->info->recscope = kRecScopeType_Variable;
00589 key->info->kwflags = db_binary_field_getint(qres, irow, 9);
00590 rank = (key->info->kwflags & 0xFFFF0000) >> 16;
00591
00592 if (rank == 0)
00593 {
00594 rankindeterminate = 1;
00595 key->info->rank = constrank++;
00596 }
00597 else
00598 {
00599 key->info->rank = rank - 1;
00600 }
00601
00602 drms_keyword_unsetperseg(key);
00603 drms_keyword_unsetintprime(key);
00604 drms_keyword_unsetextprime(key);
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 if (key->info->type == DRMS_TYPE_TIME)
00622 {
00623 char formatn = 0;
00624 char *format = key->info->format;
00625 char *unit = key->info->unit;
00626 char *unittmp = strdup(unit);
00627 char *endptr = NULL;
00628 int64_t val = strtod(format, &endptr);
00629 char tmpout[64];
00630
00631 TIME interval = 0;
00632 interval = atoinc(unittmp);
00633
00634 if (interval <= 0)
00635 {
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 if (val != 0 || endptr != format)
00648 {
00649
00650 if (val >= INT8_MIN && val <= INT8_MAX)
00651 {
00652 formatn = val;
00653 }
00654 }
00655 else if (!parse_zone(format, tmpout, sizeof(tmpout)))
00656 {
00657
00658 snprintf(unit, DRMS_MAXUNITLEN, "%s", format);
00659 }
00660
00661 snprintf(format, DRMS_MAXFORMATLEN, "%d", formatn);
00662
00663 if (*unit == '\0' ||
00664 !strcasecmp(unit, "none") ||
00665 !strcasecmp(unit, "time") ||
00666 !strtok(unittmp, " \t\b"))
00667 {
00668 snprintf(unit, DRMS_MAXUNITLEN, "%s", "UTC");
00669 }
00670 }
00671
00672 if (unittmp)
00673 {
00674 free(unittmp);
00675 }
00676 }
00677
00678 #ifdef DEBUG
00679 printf("Keyword[%4d] name = '%s'\n",i,key->info->name);
00680 printf("Keyword[%4d] type = '%d'\n",i,key->info->type);
00681 printf("Keyword[%4d] format = '%s'\n",i,key->info->format);
00682 printf("Keyword[%4d] unit = '%s'\n",i,key->info->unit);
00683 printf("Keyword[%4d] description = '%s'\n",i,key->info->description);
00684 #endif
00685 }
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695 if (rankindeterminate)
00696 {
00697 rank = 0;
00698 while (pch)
00699 {
00700 if ((pdel = strchr(pch, ',')) != NULL)
00701 {
00702 *pdel = '\0';
00703 }
00704
00705 if (!strcmp(pch, "recnum") ||
00706 !strcmp(pch, "sunum") ||
00707 !strcmp(pch, "slotnum") ||
00708 !strcmp(pch, "sessionid") ||
00709 !strcmp(pch, "sessionns"))
00710 {
00711 pch = pdel ? pdel + 1 : NULL;
00712 continue;
00713
00714
00715
00716 }
00717
00718
00719 if ((key = (DRMS_Keyword_t *)hcon_lookup_lower(&template->keywords, pch)) != NULL)
00720 {
00721 key->info->rank = rank + constrank;
00722 rank++;
00723 }
00724
00725 pch = pdel ? pdel + 1 : NULL;
00726 }
00727 }
00728
00729 if (colnames)
00730 {
00731 free(colnames);
00732 }
00733
00734 if (namespace)
00735 {
00736 free(namespace);
00737 }
00738
00739 db_free_binary_result(qres);
00740 return DRMS_SUCCESS;
00741
00742 bailout:
00743 if (colnames)
00744 {
00745 free(colnames);
00746 }
00747
00748 if (namespace)
00749 {
00750 free(namespace);
00751 }
00752
00753 db_free_binary_result(qres);
00754 return status;
00755 }
00756
00757 int drms_template_keywords(DRMS_Record_t *template)
00758 {
00759 int err = 0;
00760 char *ns = NULL;
00761 char *table = NULL;
00762 char *oid = NULL;
00763 char *serieslwr = strdup(template->seriesinfo->seriesname);
00764 char *colnames = NULL;
00765
00766 strtolower(serieslwr);
00767 get_namespace(serieslwr, &ns, &table);
00768
00769 if (serieslwr)
00770 {
00771 free(serieslwr);
00772 }
00773
00774 err = GetTableOID(template->env, ns, table, &oid);
00775
00776 if (ns)
00777 {
00778 free(ns);
00779 }
00780
00781 if (table)
00782 {
00783 free(table);
00784 }
00785
00786 if (!err)
00787 {
00788 err = GetColumnNames(template->env, oid, &colnames);
00789 }
00790
00791 if (oid)
00792 {
00793 free(oid);
00794 }
00795
00796 err = drms_template_keywords_int(template, 1, colnames);
00797
00798 if (colnames)
00799 {
00800 free(colnames);
00801 }
00802
00803 return err;
00804 }
00805
00806
00807 DRMS_Keyword_t *drms_keyword_lookup(DRMS_Record_t *rec, const char *key, int followlink)
00808 {
00809 char *lb,*rb;
00810 char tmp[DRMS_MAXKEYNAMELEN+5]={0};
00811 int segnum;
00812
00813
00814 char tmplink[DRMS_MAXLINKNAMELEN]={0};
00815 char *colonchar;
00816 int status;
00817 colonchar = strchr(key, ':');
00818 if (colonchar)
00819 {
00820 strncpy(tmplink, key, colonchar-key);
00821 rec = drms_link_follow(rec, tmplink, &status);
00822 key = colonchar+1;
00823 if (!rec || !(*key) || status)
00824 return(NULL);
00825 }
00826
00827
00828
00829 strcpy(tmp,key);
00830 if ((lb = index(tmp,'[')))
00831 {
00832 rb = lb+1;
00833 for (rb=lb+1; *rb && *rb!=']'; rb++)
00834 {
00835 if (!isdigit(*rb))
00836 break;
00837 }
00838 if (*rb!=']' || (*rb==']' && *(rb+1)!=0))
00839 return NULL;
00840 *rb = 0;
00841 segnum = atoi(lb+1);
00842 sprintf(lb,"_%03d",segnum);
00843 #ifdef DEBUG
00844 printf("Mangled keyword name = '%s'.\n",tmp);
00845 #endif
00846 if (strlen(tmp) >= DRMS_MAXKEYNAMELEN)
00847 fprintf(stderr,"WARNING keyword name too long, %s\n",tmp);
00848 }
00849 if (!followlink)
00850 return hcon_lookup_lower(&rec->keywords, tmp);
00851 return __drms_keyword_lookup(rec, tmp, 0);
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861 static DRMS_Keyword_t * __drms_keyword_lookup(DRMS_Record_t *rec,
00862 const char *key, int depth)
00863 {
00864 int stat;
00865 DRMS_Keyword_t *keyword;
00866
00867 keyword = hcon_lookup_lower(&rec->keywords, key);
00868 if (keyword!=NULL && depth<DRMS_MAXLINKDEPTH )
00869 {
00870 if (keyword->info->islink)
00871 {
00872
00873 rec = drms_link_follow(rec, keyword->info->linkname, &stat);
00874 if (stat)
00875 {
00876 if (rec)
00877 {
00878 drms_close_record(rec, DRMS_FREE_RECORD);
00879 }
00880 return NULL;
00881 }
00882 else
00883 {
00884 DRMS_Keyword_t *key = __drms_keyword_lookup(rec, keyword->info->target_key, depth+1);
00885 return key;
00886 }
00887 }
00888 else
00889 {
00890 return keyword;
00891 }
00892 }
00893 if (depth>=DRMS_MAXLINKDEPTH)
00894 fprintf(stderr, "WARNING: Max link depth exceeded for keyword '%s' in "
00895 "record %lld from series '%s'\n",keyword->info->name, rec->recnum,
00896 rec->seriesinfo->seriesname);
00897
00898 return NULL;
00899 }
00900
00901 DRMS_Type_t drms_keyword_type(DRMS_Keyword_t *key)
00902 {
00903 return key->info->type;
00904 }
00905
00906 HContainer_t *drms_keyword_createinfocon(DRMS_Env_t *drmsEnv,
00907 const char *seriesName,
00908 int *status)
00909 {
00910 HContainer_t *ret = NULL;
00911
00912 DRMS_Record_t *template = drms_template_record(drmsEnv, seriesName, status);
00913
00914 if (*status == DRMS_SUCCESS)
00915 {
00916 int size = hcon_size(&(template->keywords));
00917 if (size > 0)
00918 {
00919 char **nameArr = (char **)malloc(sizeof(char *) * size);
00920 DRMS_KeywordInfo_t **valArr =
00921 (DRMS_KeywordInfo_t **)malloc(sizeof(DRMS_KeywordInfo_t *) * size);
00922
00923 if (nameArr != NULL && valArr != NULL)
00924 {
00925 HIterator_t hit;
00926 hiter_new_sort(&hit, &(template->keywords), drms_keyword_ranksort);
00927 DRMS_Keyword_t *kw = NULL;
00928
00929 int iKW = 0;
00930 while ((kw = hiter_getnext(&hit)) != NULL)
00931 {
00932 nameArr[iKW] = kw->info->name;
00933 valArr[iKW] = kw->info;
00934
00935 iKW++;
00936 }
00937
00938 ret = hcon_create(sizeof(DRMS_KeywordInfo_t),
00939 DRMS_MAXKEYNAMELEN,
00940 NULL,
00941 NULL,
00942 (void **)valArr,
00943 nameArr,
00944 size);
00945 }
00946 else
00947 {
00948 *status = DRMS_ERROR_OUTOFMEMORY;
00949 }
00950
00951 if (nameArr != NULL)
00952 {
00953 free(nameArr);
00954 }
00955
00956 if (valArr != NULL)
00957 {
00958 free(valArr);
00959 }
00960 }
00961 }
00962
00963 return ret;
00964 }
00965
00966 void drms_keyword_destroyinfocon(HContainer_t **info)
00967 {
00968 hcon_destroy(info);
00969 }
00970
00971 int drms_keyword_keysmatch(DRMS_Keyword_t *k1, DRMS_Keyword_t *k2)
00972 {
00973 int ret = 0;
00974
00975 DRMS_KeywordInfo_t *key1 = k1->info;
00976 DRMS_KeywordInfo_t *key2 = k2->info;
00977
00978 char exp1[DRMS_MAXKEYNAMELEN];
00979 char exp2[DRMS_MAXKEYNAMELEN];
00980 int exp1Valid = fitsexport_getextkeyname(k1, exp1, sizeof(exp1));
00981 int exp2Valid = fitsexport_getextkeyname(k2, exp2, sizeof(exp2));
00982
00983 if (exp1Valid && exp2Valid)
00984 {
00985
00986 ret = (strcmp(key1->name, key2->name) == 0 &&
00987 key1->islink == key2->islink &&
00988 strcmp(key1->linkname, key2->linkname) == 0 &&
00989 strcmp(key1->target_key, key2->target_key) == 0 &&
00990 key1->type == key2->type &&
00991 drms_equal(key1->type, &(k1->value), &(k2->value)) &&
00992 strcmp(key1->format, key2->format) == 0 &&
00993 strcmp(key1->unit, key2->unit) == 0 &&
00994 strcmp(key1->description, key2->description) == 0 &&
00995 key1->recscope == key2->recscope &&
00996 drms_keyword_getperseg(k1) == drms_keyword_getperseg(k2) &&
00997 drms_keyword_getintprime(k1) == drms_keyword_getintprime(k2) &&
00998 drms_keyword_getextprime(k1) == drms_keyword_getextprime(k2));
00999
01000 ret = (ret && (strcmp(exp1, exp2) == 0));
01001 }
01002
01003 return ret;
01004 }
01005
01006
01007
01008
01009
01010 char drms_getkey_char(DRMS_Record_t *rec, const char *key, int *status)
01011 {
01012 DRMS_Keyword_t *keyword;
01013 int stat;
01014 char result;
01015
01016 keyword = drms_keyword_lookup(rec, key, 1);
01017 if (keyword != NULL )
01018 {
01019 result = drms2char(keyword->info->type, &keyword->value, &stat);
01020 }
01021 else
01022 {
01023 result = DRMS_MISSING_CHAR;
01024 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01025 }
01026 if (status)
01027 *status = stat;
01028 return result;
01029 }
01030
01031
01032 short drms_getkey_short(DRMS_Record_t *rec, const char *key, int *status)
01033 {
01034 DRMS_Keyword_t *keyword;
01035 int stat;
01036 short result;
01037
01038 keyword = drms_keyword_lookup(rec, key, 1);
01039 if (keyword!=NULL )
01040 {
01041 result = drms2short(keyword->info->type, &keyword->value, &stat);
01042 }
01043 else
01044 {
01045 result = DRMS_MISSING_SHORT;
01046 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01047 }
01048 if (status)
01049 *status = stat;
01050 return result;
01051 }
01052
01053
01054 int drms_getkey_int(DRMS_Record_t *rec, const char *key, int *status)
01055 {
01056 DRMS_Keyword_t *keyword;
01057 int stat;
01058 int result;
01059
01060 keyword = drms_keyword_lookup(rec, key, 1);
01061 if (keyword!=NULL )
01062 {
01063 result = drms2int(keyword->info->type, &keyword->value, &stat);
01064 }
01065 else
01066 {
01067 result = DRMS_MISSING_INT;
01068 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01069 }
01070 if (status)
01071 *status = stat;
01072 return result;
01073 }
01074
01075
01076 long long drms_getkey_longlong(DRMS_Record_t *rec, const char *key, int *status)
01077 {
01078 DRMS_Keyword_t *keyword;
01079 int stat;
01080 long long result;
01081
01082 keyword = drms_keyword_lookup(rec, key, 1);
01083 if (keyword!=NULL )
01084 {
01085 result = drms2longlong(keyword->info->type, &keyword->value, &stat);
01086 }
01087 else
01088 {
01089 result = DRMS_MISSING_LONGLONG;
01090 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01091 }
01092 if (status)
01093 *status = stat;
01094 return result;
01095 }
01096
01097
01098 float drms_getkey_float(DRMS_Record_t *rec, const char *key, int *status)
01099 {
01100 DRMS_Keyword_t *keyword;
01101 int stat;
01102 float result;
01103
01104 keyword = drms_keyword_lookup(rec, key, 1);
01105 if (keyword != NULL )
01106 {
01107 result = drms2float(keyword->info->type, &keyword->value, &stat);
01108 }
01109 else
01110 {
01111 result = DRMS_MISSING_FLOAT;
01112 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01113 }
01114 if (status)
01115 *status = stat;
01116 return result;
01117 }
01118
01119 double drms_getkey_double(DRMS_Record_t *rec, const char *key, int *status)
01120 {
01121 DRMS_Keyword_t *keyword;
01122 int stat;
01123 double result;
01124
01125 keyword = drms_keyword_lookup(rec, key, 1);
01126
01127 if (keyword != NULL)
01128 {
01129 result = drms_keyword_getdouble(keyword, &stat);
01130 }
01131 else
01132 {
01133 result = DRMS_MISSING_DOUBLE;
01134 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01135 }
01136
01137 if (status)
01138 *status = stat;
01139 return result;
01140 }
01141
01142 double drms_keyword_getdouble(DRMS_Keyword_t *keyword, int *status)
01143 {
01144 double result;
01145 int stat = DRMS_SUCCESS;
01146
01147 result = drms2double(keyword->info->type, &keyword->value, &stat);
01148
01149 if (status)
01150 *status = stat;
01151 return result;
01152 }
01153
01154 char *drms_keyword_getstring(DRMS_Keyword_t *keyword, int *status)
01155 {
01156 char *result = NULL;
01157 int stat = DRMS_SUCCESS;
01158
01159 if (keyword->info->type == DRMS_TYPE_TIME)
01160 {
01161 result = malloc(32);
01162 XASSERT(result);
01163 memset(result, 0, 32);
01164 drms_keyword_snprintfval(keyword, result, 32);
01165 }
01166 else
01167 {
01168 result = drms2string(keyword->info->type, &keyword->value, &stat);
01169 }
01170
01171 if (status)
01172 *status = stat;
01173 return result;
01174 }
01175
01176 char *drms_getkey_string(DRMS_Record_t *rec, const char *key, int *status)
01177 {
01178 DRMS_Keyword_t *keyword;
01179 int stat;
01180 char *result=NULL;
01181
01182 keyword = drms_keyword_lookup(rec, key, 1);
01183 if (keyword!=NULL )
01184 {
01185 result = drms_keyword_getstring(keyword, &stat);
01186 }
01187 else
01188 {
01189 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01190 copy_string(&result, DRMS_MISSING_STRING);
01191 }
01192 if (status)
01193 *status = stat;
01194 return result;
01195 }
01196
01197 TIME drms_getkey_time(DRMS_Record_t *rec, const char *key, int *status)
01198 {
01199 DRMS_Keyword_t *keyword;
01200 int stat;
01201 TIME result=DRMS_MISSING_TIME;
01202
01203 keyword = drms_keyword_lookup(rec, key, 1);
01204 if (keyword!=NULL )
01205 {
01206 result = drms_keyword_gettime(keyword, &stat);
01207 }
01208 else
01209 {
01210 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01211 }
01212 if (status)
01213 *status = stat;
01214 return result;
01215 }
01216
01217 TIME drms_keyword_gettime(DRMS_Keyword_t *keyword, int *status)
01218 {
01219 double result;
01220 int stat = DRMS_SUCCESS;
01221
01222 result = drms2time(keyword->info->type, &keyword->value, &stat);
01223
01224 if (status)
01225 *status = stat;
01226 return (TIME)result;
01227 }
01228
01229 DRMS_Type_Value_t drms_getkey(DRMS_Record_t *rec, const char *key,
01230 DRMS_Type_t *type, int *status)
01231 {
01232 DRMS_Type_Value_t value;
01233 DRMS_Keyword_t *keyword;
01234 int stat;
01235
01236 keyword = drms_keyword_lookup(rec, key, 1);
01237 if (keyword != NULL )
01238 {
01239 *type = keyword->info->type;
01240 value.string_val = NULL;
01241 drms_copy_drms2drms(keyword->info->type, &value, &keyword->value);
01242 stat = DRMS_SUCCESS;
01243 }
01244 else
01245 {
01246 *type = DRMS_TYPE_DOUBLE;
01247
01248 value.double_val = DRMS_MISSING_DOUBLE;
01249 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01250 }
01251 if (status)
01252 *status = stat;
01253
01254 return value;
01255 }
01256
01257
01258 DRMS_Value_t drms_getkey_p(DRMS_Record_t *rec, const char *key, int *status)
01259 {
01260 DRMS_Type_Value_t value;
01261 DRMS_Value_t retval;
01262 DRMS_Keyword_t *keyword;
01263 int stat;
01264
01265 keyword = drms_keyword_lookup(rec, key, 1);
01266 if (keyword != NULL )
01267 {
01268 retval.type = keyword->info->type;
01269 value.string_val = NULL;
01270 drms_copy_drms2drms(keyword->info->type, &value, &keyword->value);
01271 stat = DRMS_SUCCESS;
01272 }
01273 else
01274 {
01275 retval.type = DRMS_TYPE_DOUBLE;
01276
01277 value.double_val = DRMS_MISSING_DOUBLE;
01278 stat = DRMS_ERROR_UNKNOWNKEYWORD;
01279 }
01280 if (status)
01281 *status = stat;
01282
01283 retval.value = value;
01284
01285 return retval;
01286 }
01287
01288
01289 static int SetKeyInternal(DRMS_Record_t *rec, const char *key, DRMS_Value_t *value)
01290 {
01291 DRMS_Keyword_t *keyword = NULL;
01292 DRMS_Keyword_t *indexkw = NULL;
01293 int retstat = DRMS_MISSING_INT;
01294
01295 if (rec ->readonly)
01296 {
01297 return DRMS_ERROR_RECORDREADONLY;
01298 }
01299
01300 keyword = drms_keyword_lookup(rec, key, 0);
01301 if (keyword != NULL )
01302 {
01303 if (keyword->info->islink || drms_keyword_isconstant(keyword))
01304 {
01305 return DRMS_ERROR_KEYWORDREADONLY;
01306 }
01307 else
01308 {
01309
01310
01311 if (value->type == DRMS_TYPE_STRING && keyword->info->unit && *keyword->info->unit)
01312 {
01313 TIME interval = atoinc(keyword->info->unit);
01314 char *dupe = NULL;
01315 size_t sz;
01316
01317 if (interval > 0)
01318 {
01319 DRMS_Type_Value_t bs;
01320
01321 dupe = strdup(value->value.string_val);
01322 sz = strlen(dupe) + 1;
01323 dupe = base_strcatalloc(dupe, keyword->info->unit, &sz);
01324 if (dupe)
01325 {
01326 bs.string_val = dupe;
01327 retstat = drms_convert(keyword->info->type,
01328 &keyword->value,
01329 value->type,
01330 &bs);
01331 free(dupe);
01332 }
01333 else
01334 {
01335 return DRMS_ERROR_OUTOFMEMORY;
01336 }
01337 }
01338 }
01339
01340 if (drms_ismissing_int(retstat))
01341 {
01342 retstat = drms_convert(keyword->info->type,
01343 &keyword->value,
01344 value->type,
01345 &(value->value));
01346 }
01347
01348
01349
01350
01351 if (retstat == DRMS_INEXACT)
01352 {
01353 retstat = DRMS_SUCCESS;
01354 }
01355
01356 if (!retstat && drms_keyword_isslotted(keyword))
01357 {
01358
01359 DRMS_Value_t indexval;
01360 DRMS_Value_t inval;
01361
01362 inval.value = keyword->value;
01363 inval.type = keyword->info->type;
01364
01365 retstat = drms_keyword_slotval2indexval(keyword,
01366 &inval,
01367 &indexval,
01368 NULL);
01369
01370 if (!retstat)
01371 {
01372 indexkw = drms_keyword_indexfromslot(keyword);
01373 retstat = drms_convert(indexkw->info->type,
01374 &(indexkw->value),
01375 indexval.type,
01376 &(indexval.value));
01377 }
01378 }
01379
01380 return retstat;
01381 }
01382 }
01383 else
01384 {
01385 return DRMS_ERROR_UNKNOWNKEYWORD;
01386 }
01387 }
01388
01389 static int AppendStrKeyInternal(DRMS_Record_t *rec, const char *key, const char *val, int newline)
01390 {
01391 DRMS_Keyword_t *keyword = NULL;
01392 int rv = DRMS_SUCCESS;
01393
01394 if (rec && val && *val)
01395 {
01396 keyword = drms_keyword_lookup(rec, key, 0);
01397 if (keyword != NULL)
01398 {
01399 if (keyword->info->islink || drms_keyword_isconstant(keyword) || drms_keyword_isslotted(keyword))
01400 {
01401 rv = DRMS_ERROR_KEYWORDREADONLY;
01402 }
01403 else if (keyword->info->type != DRMS_TYPE_STRING)
01404 {
01405 rv = DRMS_ERROR_INVALIDDATA;
01406 }
01407 else
01408 {
01409
01410 if (keyword->value.string_val)
01411 {
01412 char *tmp = NULL;
01413
01414 if (*keyword->value.string_val)
01415 {
01416 size_t strsz = strlen(keyword->value.string_val) + strlen(val) + 2;
01417 tmp = malloc(strsz);
01418
01419 if (newline)
01420 {
01421 snprintf(tmp, strsz, "%s\n%s", keyword->value.string_val, val);
01422 }
01423 else
01424 {
01425 snprintf(tmp, strsz, "%s%s", keyword->value.string_val, val);
01426 }
01427 }
01428 else
01429 {
01430 tmp = strdup(val);
01431 }
01432
01433 free(keyword->value.string_val);
01434 keyword->value.string_val = tmp;
01435 }
01436 else
01437 {
01438 keyword->value.string_val = strdup(val);
01439 }
01440 }
01441 }
01442 else
01443 {
01444 rv = DRMS_ERROR_UNKNOWNKEYWORD;
01445 }
01446 }
01447 else
01448 {
01449 rv = DRMS_ERROR_INVALIDDATA;
01450 }
01451
01452 return rv;
01453 }
01454
01455 int drms_appendhistory(DRMS_Record_t *rec, const char *str, int newline)
01456 {
01457 return AppendStrKeyInternal(rec, "HISTORY", str, newline);
01458 }
01459
01460 int drms_appendcomment(DRMS_Record_t *rec, const char *str, int newline)
01461 {
01462 return AppendStrKeyInternal(rec, "COMMENT", str, newline);
01463 }
01464
01465 int drms_setkey(DRMS_Record_t *rec, const char *key, DRMS_Type_t type,
01466 DRMS_Type_Value_t *value)
01467 {
01468 DRMS_Value_t val = {type, *value};
01469 return SetKeyInternal(rec, key, &val);
01470 }
01471
01472
01473
01474 int drms_setkey_p(DRMS_Record_t *rec, const char *key, DRMS_Value_t *value)
01475 {
01476 return SetKeyInternal(rec, key, value);
01477 }
01478
01479
01480 int drms_setkey_char(DRMS_Record_t *rec, const char *key, char value)
01481 {
01482 DRMS_Type_Value_t v;
01483 v.char_val = value;
01484 DRMS_Value_t val = {DRMS_TYPE_CHAR, v};
01485 return SetKeyInternal(rec, key, &val);
01486 }
01487
01488 int drms_setkey_short(DRMS_Record_t *rec, const char *key, short value)
01489 {
01490 DRMS_Type_Value_t v;
01491 v.short_val = value;
01492 DRMS_Value_t val = {DRMS_TYPE_SHORT, v};
01493 return SetKeyInternal(rec, key, &val);
01494 }
01495
01496 int drms_setkey_int(DRMS_Record_t *rec, const char *key, int value)
01497 {
01498 DRMS_Type_Value_t v;
01499 v.int_val = value;
01500 DRMS_Value_t val = {DRMS_TYPE_INT, v};
01501 return SetKeyInternal(rec, key, &val);
01502 }
01503
01504 int drms_setkey_longlong(DRMS_Record_t *rec, const char *key, long long value)
01505 {
01506 DRMS_Type_Value_t v;
01507 v.longlong_val = value;
01508 DRMS_Value_t val = {DRMS_TYPE_LONGLONG, v};
01509 return SetKeyInternal(rec, key, &val);
01510 }
01511
01512 int drms_setkey_float(DRMS_Record_t *rec, const char *key, float value)
01513 {
01514 DRMS_Type_Value_t v;
01515 v.float_val = value;
01516 DRMS_Value_t val = {DRMS_TYPE_FLOAT, v};
01517 return SetKeyInternal(rec, key, &val);
01518 }
01519
01520 int drms_setkey_double(DRMS_Record_t *rec, const char *key, double value)
01521 {
01522 DRMS_Type_Value_t v;
01523 v.double_val = value;
01524 DRMS_Value_t val = {DRMS_TYPE_DOUBLE, v};
01525 return SetKeyInternal(rec, key, &val);
01526 }
01527
01528 int drms_setkey_time(DRMS_Record_t *rec, const char *key, TIME value)
01529 {
01530 DRMS_Type_Value_t v;
01531 v.time_val = value;
01532 DRMS_Value_t val = {DRMS_TYPE_TIME, v};
01533 return SetKeyInternal(rec, key, &val);
01534 }
01535
01536 int drms_setkey_string(DRMS_Record_t *rec, const char *key, const char *value)
01537 {
01538 int ret;
01539
01540 DRMS_Type_Value_t v;
01541 v.string_val = strdup(value);
01542 DRMS_Value_t val = {DRMS_TYPE_STRING, v};
01543 ret = SetKeyInternal(rec, key, &val);
01544 free(v.string_val);
01545 v.string_val = NULL;
01546 return ret;
01547 }
01548
01549 int drms_appkey_string(DRMS_Record_t *rec, const char *key, const char *value)
01550 {
01551 return AppendStrKeyInternal(rec, key, value, 0);
01552 }
01553
01554 int drms_keyword_inclass(DRMS_Keyword_t *key, DRMS_KeywordClass_t class)
01555 {
01556 int inclass = 0;
01557
01558 switch(class)
01559 {
01560 case kDRMS_KeyClass_All:
01561 inclass = 1;
01562 break;
01563 case kDRMS_KeyClass_Explicit:
01564 inclass = !(drms_keyword_getimplicit(key));
01565 break;
01566 case kDRMS_KeyClass_DRMSPrime:
01567 inclass = drms_keyword_getextprime(key);
01568 break;
01569 case kDRMS_KeyClass_Persegment:
01570 inclass = drms_keyword_getperseg(key);
01571 break;
01572 }
01573
01574 return inclass;
01575 }
01576
01577 int drms_copykey(DRMS_Record_t *target, DRMS_Record_t *source, const char *key)
01578 {
01579 int status = DRMS_SUCCESS;
01580 DRMS_Value_t srcval;
01581
01582
01583 srcval = drms_getkey_p(source, key, &status);
01584
01585 if (status == DRMS_SUCCESS)
01586 {
01587
01588 status = drms_setkey_p(target, key, &srcval);
01589 }
01590
01591 drms_value_free(&srcval);
01592
01593 return status;
01594 }
01595
01596 int drms_copykeyB(DRMS_Keyword_t *tgtkey, DRMS_Keyword_t *srckey)
01597 {
01598 return drms_copykey(tgtkey->record, srckey->record, srckey->info->name);
01599 }
01600
01601 int drms_copykeys(DRMS_Record_t *target,
01602 DRMS_Record_t *source,
01603 int usesrcset,
01604 DRMS_KeywordClass_t class)
01605 {
01606 HIterator_t sethit;
01607 DRMS_Keyword_t *srckey = NULL;
01608 DRMS_Keyword_t *tgtkey = NULL;
01609 DRMS_Keyword_t *setkey = NULL;
01610 DRMS_Keyword_t *lookupkey = NULL;
01611 DRMS_Record_t *lookuprec = NULL;
01612 int status = DRMS_SUCCESS;
01613
01614 if (usesrcset)
01615 {
01616 hiter_new_sort(&sethit, &source->keywords, drms_keyword_ranksort);
01617 lookuprec = target;
01618 }
01619 else
01620 {
01621 hiter_new_sort(&sethit, &target->keywords, drms_keyword_ranksort);
01622 lookuprec = source;
01623 }
01624
01625 while ((setkey = (DRMS_Keyword_t *)hiter_getnext(&sethit)) != NULL)
01626 {
01627 if (drms_keyword_inclass(setkey, class))
01628 {
01629 lookupkey = drms_keyword_lookup(lookuprec, setkey->info->name, 1);
01630
01631 if (usesrcset)
01632 {
01633 srckey = setkey;
01634 tgtkey = lookupkey;
01635 }
01636 else
01637 {
01638 srckey = lookupkey;
01639 tgtkey = setkey;
01640 }
01641
01642 if (tgtkey && srckey)
01643 {
01644 if (!drms_keyword_islinked(tgtkey) && !drms_keyword_isconstant(tgtkey))
01645 {
01646
01647
01648 status = drms_copykeyB(tgtkey, srckey);
01649 }
01650 }
01651 }
01652
01653 if (status)
01654 {
01655 if (usesrcset)
01656 {
01657 fprintf(stderr, "drms_copykeys() failed on keyword '%s' with status '%d'.\n", srckey->info->name, status);
01658 }
01659 else
01660 {
01661 fprintf(stderr, "drms_copykeys() failed on keyword '%s' with status '%d'.\n", tgtkey->info->name, status);
01662 }
01663 break;
01664 }
01665 }
01666
01667 hiter_free(&sethit);
01668
01669 return status;
01670 }
01671
01672 int drms_keyword_getsegscope(DRMS_Keyword_t *key)
01673 {
01674 return drms_keyword_getperseg(key);
01675 }
01676
01677 DRMS_RecScopeType_t drms_keyword_getrecscope(DRMS_Keyword_t *key)
01678 {
01679 return key->info->recscope;
01680 }
01681
01682 const char *drms_keyword_getrecscopestr(DRMS_Keyword_t *key, int *status)
01683 {
01684 int stat = DRMS_SUCCESS;
01685 const char *ret = NULL;
01686 const char **pRet = NULL;
01687 char buf[kMaxRecScopeTypeKey];
01688
01689 if (!gRecScopeStrHC)
01690 {
01691 gRecScopeStrHC = hcon_create(sizeof(const char *),
01692 kMaxRecScopeTypeKey,
01693 NULL,
01694 NULL,
01695 NULL,
01696 NULL,
01697 0);
01698
01699 if (gRecScopeStrHC)
01700 {
01701 int i = 0;
01702
01703 while (gSS[i].type != -99)
01704 {
01705 snprintf(buf, sizeof(buf), "%d", (int)gSS[i].type);
01706 hcon_insert_lower(gRecScopeStrHC, buf, &(gSS[i].str));
01707 i++;
01708 }
01709 }
01710 else
01711 {
01712 fprintf(stderr, "Error creating record scope type string container.\n");
01713 stat = DRMS_ERROR_CANTCREATEHCON;
01714 }
01715 }
01716
01717 if (gRecScopeStrHC)
01718 {
01719 snprintf(buf, sizeof(buf), "%d", (int)key->info->recscope);
01720 pRet = (const char **)hcon_lookup(gRecScopeStrHC, buf);
01721
01722 if (pRet == NULL)
01723 {
01724 fprintf(stderr, "Invalid record scope type %d.\n", (int)key->info->recscope);
01725 stat = DRMS_ERROR_INVALIDRECSCOPETYPE;
01726 }
01727 else
01728 {
01729 ret = *pRet;
01730 }
01731 }
01732
01733 if (status)
01734 {
01735 *status = stat;
01736 }
01737
01738 return ret;
01739 }
01740
01741 DRMS_RecScopeType_t drms_keyword_str2recscope(const char *str, int *status)
01742 {
01743 int stat = DRMS_SUCCESS;
01744 DRMS_RecScopeType_t ret = kRecScopeType_Variable;
01745
01746 if (!gRecScopeHC)
01747 {
01748 gRecScopeHC = hcon_create(sizeof(int),
01749 kMaxRecScopeTypeKey,
01750 NULL,
01751 NULL,
01752 NULL,
01753 NULL,
01754 0);
01755
01756 if (gRecScopeHC)
01757 {
01758 int i = 0;
01759
01760 while (gSS[i].type != -99)
01761 {
01762 hcon_insert_lower(gRecScopeHC, gSS[i].str, (int *)(&(gSS[i].type)));
01763 i++;
01764 }
01765 }
01766 else
01767 {
01768 fprintf(stderr, "Error creating record scope type container.\n");
01769 stat = DRMS_ERROR_CANTCREATEHCON;
01770 }
01771 }
01772
01773 if (gRecScopeHC)
01774 {
01775 int *pVal = (int *)hcon_lookup_lower(gRecScopeHC, str);
01776
01777 if (pVal == NULL)
01778 {
01779 fprintf(stderr, "Invalid record scope type string %s.\n", str);
01780 stat = DRMS_ERROR_INVALIDRECSCOPETYPE;
01781 }
01782 else
01783 {
01784 ret = (DRMS_RecScopeType_t)(*pVal);
01785 }
01786 }
01787
01788 if (status)
01789 {
01790 *status = stat;
01791 }
01792
01793 return ret;
01794 }
01795
01796 int drms_keyword_isvariable(DRMS_Keyword_t *key)
01797 {
01798 return (key->info->recscope != kRecScopeType_Constant);
01799 }
01800
01801 int drms_keyword_isconstant(DRMS_Keyword_t *key)
01802 {
01803 return (key->info->recscope == kRecScopeType_Constant);
01804 }
01805
01806 int drms_keyword_isindex(DRMS_Keyword_t *key)
01807 {
01808 return (key->info->recscope >= kRecScopeIndex_B &&
01809 key->info->recscope < kRecScopeSlotted_B);
01810 }
01811
01812 int drms_keyword_isslotted(DRMS_Keyword_t *key)
01813 {
01814 return (key->info->recscope >= kRecScopeSlotted_B);
01815 }
01816
01817 int drms_keyword_islinked(DRMS_Keyword_t *key)
01818 {
01819 return (key->info->islink != 0);
01820 }
01821
01822 int drms_keyword_isprime(DRMS_Keyword_t *key)
01823 {
01824 return drms_keyword_getintprime(key);
01825 }
01826
01827 DRMS_Type_t drms_keyword_gettype(DRMS_Keyword_t *key)
01828 {
01829 return key->info->type;
01830 }
01831
01832 const DRMS_Type_Value_t *drms_keyword_getvalue(DRMS_Keyword_t *key)
01833 {
01834 return &(key->value);
01835 }
01836
01837
01838 DRMS_SlotKeyUnit_t drms_keyword_getslotunit(DRMS_Keyword_t *slotkey, int *status)
01839 {
01840 DRMS_SlotKeyUnit_t ret = kSlotKeyUnit_Invalid;
01841 int stat = DRMS_SUCCESS;
01842 DRMS_Keyword_t *unitKey = NULL;
01843
01844 if (slotkey)
01845 {
01846 unitKey = drms_keyword_unitfromslot(slotkey);
01847 }
01848 else
01849 {
01850 fprintf(stderr,
01851 "Keyword '%s' is not associated with a unit ancillary keyword.\n",
01852 slotkey->info->name);
01853 }
01854
01855 if (unitKey)
01856 {
01857 ret = drms_keyword_getunit(unitKey, &stat);
01858 }
01859
01860 if (ret == kSlotKeyUnit_Invalid)
01861 {
01862 stat = DRMS_ERROR_INVALIDDATA;
01863 }
01864
01865 if (status)
01866 {
01867 *status = stat;
01868 }
01869
01870 return ret;
01871 }
01872
01873
01874 DRMS_SlotKeyUnit_t drms_keyword_getunit(DRMS_Keyword_t *key, int *status)
01875 {
01876 DRMS_SlotKeyUnit_t ret = kSlotKeyUnit_Invalid;
01877 char buf[kMaxSlotUnitKey];
01878 int stat = DRMS_SUCCESS;
01879
01880 if (key->info->type == DRMS_TYPE_STRING && strstr(key->info->name, kSlotAncKey_Unit))
01881 {
01882 if (!gSlotUnitHC)
01883 {
01884 gSlotUnitHC = hcon_create(sizeof(int),
01885 kMaxSlotUnitKey,
01886 NULL,
01887 NULL,
01888 NULL,
01889 NULL,
01890 0);
01891
01892 if (gSlotUnitHC)
01893 {
01894 int i = 0;
01895
01896 while (gSUS[i].type != -99)
01897 {
01898 snprintf(buf, sizeof(buf), "%s", gSUS[i].str);
01899 hcon_insert_lower(gSlotUnitHC, buf, &(gSUS[i].type));
01900 i++;
01901 }
01902 }
01903 else
01904 {
01905 fprintf(stderr, "Error creating slot unit string container.\n");
01906 stat = DRMS_ERROR_CANTCREATEHCON;
01907 }
01908 }
01909
01910 DRMS_SlotKeyUnit_t *pSU = hcon_lookup_lower(gSlotUnitHC, (key->value).string_val);
01911 if (pSU)
01912 {
01913 ret = *pSU;
01914 }
01915 }
01916 else
01917 {
01918 fprintf(stderr,
01919 "Keyword '%s' does not contain slotted keyword unit information.\n",
01920 key->info->name);
01921 }
01922
01923 if (status)
01924 {
01925 *status = stat;
01926 }
01927
01928 return ret;
01929 }
01930
01931
01932 TIME drms_keyword_getslotepoch(DRMS_Keyword_t *slotkey, int *status)
01933 {
01934 TIME ret = DRMS_MISSING_TIME;
01935 int stat = DRMS_SUCCESS;
01936 DRMS_Keyword_t *epochKey = NULL;
01937
01938 if (slotkey)
01939 {
01940
01941 epochKey = drms_keyword_epochfromslot(slotkey);
01942
01943 if (epochKey)
01944 {
01945 ret = drms_keyword_getepoch(epochKey, &stat);
01946 }
01947 else
01948 {
01949 fprintf(stderr,
01950 "Keyword '%s' is not associated with an epoch ancillary keyword.\n",
01951 slotkey->info->name);
01952 }
01953 }
01954
01955 if (drms_ismissing_time(ret))
01956 {
01957 stat = DRMS_ERROR_INVALIDDATA;
01958 }
01959
01960 if (status)
01961 {
01962 *status = stat;
01963 }
01964
01965 return ret;
01966 }
01967
01968
01969 TIME drms_keyword_getepoch(DRMS_Keyword_t *key, int *status)
01970 {
01971 TIME ret = DRMS_MISSING_TIME;
01972 int stat = DRMS_SUCCESS;
01973
01974 if (key->info->type == DRMS_TYPE_STRING && strstr(key->info->name, kSlotAncKey_Epoch))
01975 {
01976 const TIME *timeval = drms_time_getepoch((key->value).string_val, NULL, &stat);
01977
01978 if (timeval)
01979 {
01980 ret = *timeval;
01981 }
01982 else
01983 {
01984 fprintf(stderr, "Invalid slot unit string value '%s'.\n", (key->value).string_val);
01985 }
01986 }
01987 else if (key->info->type == DRMS_TYPE_TIME)
01988 {
01989 ret = drms_keyword_gettime(key, NULL);
01990 }
01991 else
01992 {
01993 fprintf(stderr,
01994 "Keyword '%s' does not contain slotted keyword epoch information.\n",
01995 key->info->name);
01996 }
01997
01998 if (status)
01999 {
02000 *status = stat;
02001 }
02002
02003 return ret;
02004 }
02005
02006 double drms_keyword_getslotcarr0(void)
02007 {
02008 return kSlotKeyBase_Carr;
02009 }
02010
02011 double drms_keyword_getslotbase(DRMS_Keyword_t *slotkey, int *status)
02012 {
02013 double ret = DRMS_MISSING_DOUBLE;
02014 int stat = DRMS_SUCCESS;
02015
02016 if (slotkey)
02017 {
02018 switch (slotkey->info->recscope)
02019 {
02020 case kRecScopeType_TS_EQ:
02021 case kRecScopeType_TS_SLOT:
02022 ret = drms_keyword_getslotepoch(slotkey, status);
02023 break;
02024 case kRecScopeType_SLOT:
02025 {
02026 DRMS_Keyword_t *baseKey = drms_keyword_basefromslot(slotkey);
02027
02028 if (baseKey)
02029 {
02030 ret = drms2double(baseKey->info->type, &baseKey->value, &stat);
02031 }
02032 else
02033 {
02034 fprintf(stderr,
02035 "Keyword '%s' is not associated with a base ancillary keyword.\n",
02036 slotkey->info->name);
02037 }
02038
02039 if (drms_ismissing_double(ret))
02040 {
02041 stat = DRMS_ERROR_INVALIDDATA;
02042 }
02043 }
02044 break;
02045 case kRecScopeType_ENUM:
02046 break;
02047 case kRecScopeType_CARR:
02048 ret = drms_keyword_getslotcarr0();
02049 break;
02050 default:
02051 fprintf(stderr,
02052 "Invalid recscope type '%d'.\n",
02053 (int)slotkey->info->recscope);
02054 }
02055 }
02056 else
02057 {
02058 stat = DRMS_ERROR_INVALIDDATA;
02059 }
02060
02061 if (status)
02062 {
02063 *status = stat;
02064 }
02065
02066 return ret;
02067 }
02068
02069 double drms_keyword_getvalkeybase(DRMS_Keyword_t *valkey, int *status)
02070 {
02071 double ret = DRMS_MISSING_DOUBLE;
02072 int statint = DRMS_SUCCESS;
02073
02074 if (drms_keyword_isslotted(valkey))
02075 {
02076 return drms_keyword_getslotbase(valkey, status);
02077 }
02078 else
02079 {
02080
02081
02082 DRMS_Keyword_t *baseKey = drms_keyword_basefromvalkey(valkey);
02083
02084 if (baseKey)
02085 {
02086 ret = drms2double(baseKey->info->type, &baseKey->value, &statint);
02087 }
02088 else
02089 {
02090 statint = DRMS_ERROR_UNKNOWNKEYWORD;
02091 }
02092
02093 if (status)
02094 {
02095 *status = statint;
02096 }
02097
02098 return ret;
02099 }
02100 }
02101
02102
02103 double drms_keyword_getslotstep(DRMS_Keyword_t *slotkey, DRMS_SlotKeyUnit_t *unit, int *status)
02104 {
02105 double ret = DRMS_MISSING_DOUBLE;
02106 int stat = DRMS_SUCCESS;
02107 DRMS_Keyword_t *stepKey = NULL;
02108
02109 if (slotkey)
02110 {
02111 stepKey = drms_keyword_stepfromslot(slotkey);
02112 }
02113 else
02114 {
02115 fprintf(stderr,
02116 "Keyword '%s' is not associated with a step ancillary keyword.\n",
02117 slotkey->info->name);
02118 }
02119
02120 if (stepKey)
02121 {
02122 ret = drms_keyword_getstep(stepKey, slotkey->info->recscope, unit, &stat);
02123 }
02124
02125 if (stat == DRMS_SUCCESS)
02126 {
02127 if (drms_ismissing_double(ret))
02128 {
02129 stat = DRMS_ERROR_INVALIDDATA;
02130 }
02131 }
02132
02133 if (status)
02134 {
02135 *status = stat;
02136 }
02137
02138 return ret;
02139 }
02140
02141
02142 double drms_keyword_getstep(DRMS_Keyword_t *key,
02143 DRMS_RecScopeType_t recscope,
02144 DRMS_SlotKeyUnit_t *unit,
02145 int *status)
02146 {
02147 double step = DRMS_MISSING_DOUBLE;
02148 int stat = DRMS_SUCCESS;
02149
02150 if (unit)
02151 {
02152 *unit = kSlotKeyUnit_Invalid;
02153 }
02154
02155 if (drms_keyword_gettype(key) == DRMS_TYPE_STRING)
02156 {
02157 switch (recscope)
02158 {
02159 case kRecScopeType_TS_EQ:
02160
02161 case kRecScopeType_TS_SLOT:
02162 {
02163
02164 char *durstr = drms_keyword_getstring(key, NULL);
02165 if (durstr)
02166 {
02167
02168
02169
02170
02171 if (drms_names_parseduration(&durstr, &step, 0))
02172 {
02173 fprintf(stderr,
02174 "Invalid step keyword value for '%s'.\n",
02175 key->info->name);
02176 stat = DRMS_ERROR_INVALIDDATA;
02177 }
02178
02179 if (unit)
02180 {
02181 *unit = kSlotKeyUnit_Seconds;
02182 }
02183
02184 free(durstr);
02185 }
02186 }
02187 break;
02188 case kRecScopeType_CARR:
02189 {
02190
02191 char *deltastr = drms_keyword_getstring(key, NULL);
02192 if (deltastr)
02193 {
02194
02195 if (drms_names_parsedegreedelta(&deltastr, unit, &step))
02196 {
02197 fprintf(stderr,
02198 "Invalid step keyword value for '%s'.\n",
02199 key->info->name);
02200 stat = DRMS_ERROR_INVALIDDATA;
02201 }
02202
02203 free(deltastr);
02204 }
02205 }
02206 break;
02207 default:
02208
02209
02210
02211 fprintf(stderr,
02212 "Invalid recscope type '%d'.\n",
02213 (int)recscope);
02214
02215 }
02216 }
02217 else
02218 {
02219 step = drms_keyword_getdouble(key, NULL);
02220 }
02221
02222 if (*status)
02223 *status = stat;
02224
02225 return step;
02226 }
02227
02228 double drms_keyword_getvalkeystep(DRMS_Keyword_t *valkey, int *status)
02229 {
02230 double ret = DRMS_MISSING_DOUBLE;
02231 int statint = DRMS_SUCCESS;
02232
02233 if (drms_keyword_isslotted(valkey))
02234 {
02235 DRMS_SlotKeyUnit_t unit;
02236 return drms_keyword_getslotstep(valkey, &unit, status);
02237 }
02238 else
02239 {
02240
02241
02242 DRMS_Keyword_t *stepKey = drms_keyword_stepfromvalkey(valkey);
02243
02244 if (stepKey)
02245 {
02246 ret = drms2double(stepKey->info->type, &stepKey->value, &statint);
02247 }
02248 else
02249 {
02250 statint = DRMS_ERROR_UNKNOWNKEYWORD;
02251 }
02252
02253 if (status)
02254 {
02255 *status = statint;
02256 }
02257
02258 return ret;
02259 }
02260 }
02261
02262 static DRMS_Keyword_t *GetAncillaryKey(DRMS_Keyword_t *valkey, const char *suffix)
02263 {
02264 DRMS_Keyword_t *ret = NULL;
02265 char buf[DRMS_MAXKEYNAMELEN];
02266
02267 snprintf(buf, sizeof(buf), "%s%s", valkey->info->name, suffix);
02268 ret = (DRMS_Keyword_t *)hcon_lookup_lower(&(valkey->record->keywords), buf);
02269
02270 return ret;
02271 }
02272
02273 DRMS_Keyword_t *drms_keyword_indexfromslot(DRMS_Keyword_t *slot)
02274 {
02275 return GetAncillaryKey(slot, kSlotAncKey_Index);
02276 }
02277
02278 DRMS_Keyword_t *drms_keyword_indexfromvalkey(DRMS_Keyword_t *valkey)
02279 {
02280 DRMS_Keyword_t *ret = NULL;
02281
02282 if (drms_keyword_isslotted(valkey))
02283 {
02284 ret = drms_keyword_indexfromslot(valkey);
02285 }
02286 else
02287 {
02288
02289 ret = GetAncillaryKey(valkey, kSlotAncKey_Index);
02290 }
02291
02292 return ret;
02293 }
02294
02295 DRMS_Keyword_t *drms_keyword_epochfromslot(DRMS_Keyword_t *slot)
02296 {
02297 return GetAncillaryKey(slot, kSlotAncKey_Epoch);
02298 }
02299
02300
02301
02302 DRMS_Keyword_t *drms_keyword_basefromslot(DRMS_Keyword_t *slotkey)
02303 {
02304 if (slotkey->info->recscope == kRecScopeType_TS_EQ ||
02305 slotkey->info->recscope == kRecScopeType_TS_SLOT)
02306 {
02307 return GetAncillaryKey(slotkey, kSlotAncKey_Epoch);
02308 }
02309 else
02310 {
02311 return GetAncillaryKey(slotkey, kSlotAncKey_Base);
02312 }
02313 }
02314
02315 DRMS_Keyword_t *drms_keyword_basefromvalkey(DRMS_Keyword_t *valkey)
02316 {
02317 if (drms_keyword_isslotted(valkey))
02318 {
02319 return drms_keyword_basefromslot(valkey);
02320 }
02321 else
02322 {
02323 return GetAncillaryKey(valkey, kSlotAncKey_Base);
02324 }
02325 }
02326
02327 DRMS_Keyword_t *drms_keyword_stepfromslot(DRMS_Keyword_t *slot)
02328 {
02329 return GetAncillaryKey(slot, kSlotAncKey_Step);
02330 }
02331
02332 DRMS_Keyword_t *drms_keyword_stepfromvalkey(DRMS_Keyword_t *valkey)
02333 {
02334 if (drms_keyword_isslotted(valkey))
02335 {
02336 return drms_keyword_stepfromslot(valkey);
02337 }
02338 else
02339 {
02340 return GetAncillaryKey(valkey, kSlotAncKey_Step);
02341 }
02342 }
02343
02344 DRMS_Keyword_t *drms_keyword_unitfromslot(DRMS_Keyword_t *slot)
02345 {
02346 return GetAncillaryKey(slot, kSlotAncKey_Unit);
02347 }
02348
02349 DRMS_Keyword_t *drms_keyword_roundfromslot(DRMS_Keyword_t *slot)
02350 {
02351 return GetAncillaryKey(slot, kSlotAncKey_Round);
02352 }
02353
02354 DRMS_Keyword_t *drms_keyword_slotfromindex(DRMS_Keyword_t *indx)
02355 {
02356 DRMS_Keyword_t *ret = NULL;
02357 char *kname = strdup(indx->info->name);
02358
02359 if (kname)
02360 {
02361 char *underscore = strstr(kname, kSlotAncKey_Index);
02362
02363 if (underscore && drms_keyword_isindex(indx))
02364 {
02365 DRMS_Record_t *template =
02366 drms_template_record(indx->record->env,
02367 indx->record->seriesinfo->seriesname,
02368 NULL);
02369 *underscore = '\0';
02370 ret = (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords), kname);
02371 }
02372
02373 free(kname);
02374 }
02375
02376 return ret;
02377 }
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388 int drms_keyword_slotval2indexval(DRMS_Keyword_t *slotkey,
02389 DRMS_Value_t *valin,
02390 DRMS_Value_t *valout,
02391 DRMS_Value_t *startdur)
02392 {
02393 int stat = DRMS_SUCCESS;
02394
02395 if (valin && valout && drms_keyword_isslotted(slotkey))
02396 {
02397 valout->type = kIndexKWType;
02398 drms_missing(valout->type, &(valout->value));
02399
02400
02401 double step;
02402 double stepsecs;
02403 double roundstep = 0.0;
02404 DRMS_SlotKeyUnit_t unit;
02405 double unitVal;
02406 int usedefunit = 0;
02407 int round_down = 0;
02408
02409 DRMS_Keyword_t *stepKey = drms_keyword_stepfromslot(slotkey);
02410 DRMS_Keyword_t *unitKey = drms_keyword_unitfromslot(slotkey);
02411 DRMS_Keyword_t *roundKey = drms_keyword_roundfromslot(slotkey);
02412
02413 double base;
02414 double valind;
02415
02416 if (roundKey)
02417 {
02418 roundstep = drms_keyword_getdouble(roundKey, NULL);
02419 }
02420
02421 step = drms_keyword_getslotstep(slotkey, &unit, &stat);
02422
02423
02424 if (base_doubleIsEqual(step, 0.0))
02425 {
02426 fprintf(stderr, "Invalid step size of 0.0.");
02427 return DRMS_ERROR_INVALIDDATA;
02428 }
02429
02430
02431
02432 if (unit != kSlotKeyUnit_Invalid)
02433 {
02434 if (unitKey)
02435 {
02436
02437 fprintf(stderr, "Warning: '%s' specifies step unit, so '%s' will be ignored.\n", stepKey->info->name, unitKey->info->name);
02438 }
02439 }
02440 else
02441 {
02442 if (unitKey)
02443 {
02444 unit = drms_keyword_getunit(unitKey, NULL);
02445 }
02446 else
02447 {
02448 usedefunit = 1;
02449 }
02450 }
02451
02452 DRMS_RecScopeType_t recscope = drms_keyword_getrecscope(slotkey);
02453 switch (recscope)
02454 {
02455 case kRecScopeType_TS_SLOT:
02456 round_down = 1;
02457
02458 case kRecScopeType_TS_EQ:
02459 {
02460 TIME epoch;
02461
02462 epoch = drms_keyword_getslotepoch(slotkey, &stat);
02463 base = epoch;
02464
02465 if (usedefunit)
02466 {
02467 unit = kSlotKeyUnit_Seconds;
02468 }
02469
02470 switch(unit)
02471 {
02472 case kSlotKeyUnit_TSeconds:
02473 unitVal = 0.1;
02474 break;
02475 case kSlotKeyUnit_Seconds:
02476 unitVal = 1.0;
02477 break;
02478 case kSlotKeyUnit_Minutes:
02479 unitVal = 60.0;
02480 break;
02481 case kSlotKeyUnit_Days:
02482 unitVal = 86400.0;
02483 break;
02484 default:
02485 fprintf(stderr, "Invalid slotted key unit '%d'.\n", (int)unit);
02486 break;
02487 }
02488
02489 valind = valin->value.time_val;
02490 }
02491 break;
02492 case kRecScopeType_CARR:
02493 {
02494 base = drms_keyword_getslotcarr0();
02495
02496 if (usedefunit)
02497 {
02498 unit = kSlotKeyUnit_Degrees;
02499 }
02500
02501 switch(unit)
02502 {
02503 case kSlotKeyUnit_Degrees:
02504 unitVal = 1.0;
02505 break;
02506 case kSlotKeyUnit_Arcminutes:
02507 unitVal = 1/ 60.0;
02508 break;
02509 case kSlotKeyUnit_Arcseconds:
02510 unitVal = 1/ 3600.0;
02511 break;
02512 case kSlotKeyUnit_MAS:
02513 unitVal = 1 / 3600000.0;
02514 break;
02515 case kSlotKeyUnit_Radians:
02516 unitVal = 180.0 / (M_PI);
02517 break;
02518 case kSlotKeyUnit_MicroRadians:
02519 unitVal = (180.0 / (M_PI)) / 1000.0;
02520 break;
02521 default:
02522 fprintf(stderr, "Invalid slotted key unit '%d'.\n", (int)unit);
02523 break;
02524 }
02525
02526 valind = drms2double(valin->type, &(valin->value), NULL);
02527 }
02528 break;
02529 case kRecScopeType_SLOT:
02530 {
02531 base = drms_keyword_getslotbase(slotkey, &stat);
02532 unitVal = 1.0;
02533
02534 valind = drms2double(valin->type, &valin->value, &stat);
02535 }
02536 break;
02537 default:
02538 fprintf(stderr, "Invalid rec scope '%d'.\n", (int)recscope);
02539 stat = DRMS_ERROR_INVALIDDATA;
02540 }
02541
02542 stepsecs = unitVal * step;
02543 double exact = 0;
02544 int inexact = 0;
02545 int toosmall = 0;
02546
02547 if (round_down)
02548 {
02549 if (startdur)
02550 {
02551
02552 exact = valind / stepsecs;
02553 inexact = (int)exact;
02554
02555 if (valind < stepsecs)
02556 {
02557 toosmall = 1;
02558 fprintf(stderr, "Invalid slotted-keyword duration '%f seconds' specified. Should be at least the step size of '%f seconds'. Duration was rounded up to step size.\n", valind, stepsecs);
02559
02560 valout->value.longlong_val = CalcSlot(stepsecs, 0.0, stepsecs, roundstep);
02561 }
02562 else
02563 {
02564 valout->value.longlong_val = CalcSlot(inexact * stepsecs, 0.0, stepsecs, roundstep);
02565 }
02566 }
02567 else
02568 valout->value.longlong_val = CalcSlot(valind, base, stepsecs, roundstep);
02569 }
02570 else
02571 {
02572 if (startdur)
02573 {
02574
02575 exact = valind / stepsecs;
02576 inexact = (int)exact;
02577
02578 if (valind < stepsecs)
02579 {
02580 toosmall = 1;
02581 fprintf(stderr, "Invalid slotted-keyword duration '%f seconds' specified. Should be at least the step size of '%f seconds'. Duration was rounded up to step size.\n", valind, stepsecs);
02582
02583 valout->value.longlong_val = CalcSlot(stepsecs, 0.0, stepsecs, stepsecs);
02584 }
02585 else
02586 {
02587 valout->value.longlong_val = CalcSlot(inexact * stepsecs, 0.0, stepsecs, stepsecs);
02588 }
02589 }
02590 else
02591 valout->value.longlong_val = CalcSlot(valind, base, stepsecs, stepsecs);
02592 }
02593 }
02594 else
02595 {
02596 stat = DRMS_ERROR_INVALIDDATA;
02597 }
02598
02599 return stat;
02600 }
02601
02602 void drms_keyword_setdate(DRMS_Record_t *rec)
02603 {
02604
02605 TIME today = CURRENT_SYSTEM_TIME;
02606
02607
02608 if (drms_setkey_time(rec, kDATEKEYNAME, today))
02609 {
02610 fprintf(stderr, "Couldn't set DATE keyword.\n");
02611 }
02612 }
02613
02614 TIME drms_keyword_getdate(DRMS_Record_t *rec)
02615 {
02616 int status = DRMS_SUCCESS;
02617 TIME thedate = DRMS_MISSING_TIME;
02618
02619 thedate = drms_getkey_time(rec, kDATEKEYNAME, &status);
02620
02621 if (status)
02622 {
02623 fprintf(stderr, "Couldn't get DATE keyword.\n");
02624 }
02625
02626 return thedate;
02627 }
02628
02629 static DRMS_Keyword_t *TemplateKeyFollowLink(DRMS_Keyword_t *srckey, int depth, int jsd, int *statret)
02630 {
02631 int status = DRMS_SUCCESS;
02632 DRMS_Link_t *link = NULL;
02633 DRMS_Record_t *linktempl = NULL;
02634 DRMS_Keyword_t *tgtkey = NULL;
02635
02636
02637 link = (DRMS_Link_t *)hcon_lookup_lower(&srckey->record->links, srckey->info->linkname);
02638 if (link)
02639 {
02640 if (jsd)
02641 {
02642 linktempl = drms_create_jsdtemplate_record(srckey->record->env, link->info->target_series, &status);
02643 }
02644 else
02645 {
02646 linktempl = drms_template_record(srckey->record->env, link->info->target_series, &status);
02647 }
02648
02649 if (linktempl)
02650 {
02651 tgtkey = (DRMS_Keyword_t *)hcon_lookup_lower(&linktempl->keywords, srckey->info->target_key);
02652
02653 if (tgtkey)
02654 {
02655 if (tgtkey->info->islink)
02656 {
02657 if (depth < DRMS_MAXLINKDEPTH)
02658 {
02659 tgtkey = TemplateKeyFollowLink(tgtkey, depth + 1, jsd, statret);
02660 }
02661 else
02662 {
02663 fprintf(stderr,
02664 "WARNING: Max link depth exceeded for keyword '%s' in series '%s'.\n",
02665 srckey->info->name,
02666 link->info->target_series);
02667 }
02668 }
02669 }
02670 else
02671 {
02672 if (statret)
02673 {
02674 *statret = DRMS_ERROR_UNKNOWNKEYWORD;
02675 }
02676 }
02677
02678 if (jsd)
02679 {
02680 drms_destroy_jsdtemplate_record(&linktempl);
02681 }
02682 }
02683 else
02684 {
02685 if (statret)
02686 {
02687 *statret = DRMS_ERROR_UNKNOWNSERIES;
02688 }
02689 }
02690 }
02691 else
02692 {
02693 if (statret)
02694 {
02695 *statret = DRMS_ERROR_UNKNOWNLINK;
02696 }
02697 }
02698
02699 return tgtkey;
02700 }
02701
02702 DRMS_Keyword_t *drms_template_keyword_followlink(DRMS_Keyword_t *srckey, int *statret)
02703 {
02704 return TemplateKeyFollowLink(srckey, 0, 0, statret);
02705 }
02706
02707 DRMS_Keyword_t *drms_jsd_template_keyword_followlink(DRMS_Keyword_t *srckey, int *statret)
02708 {
02709 return TemplateKeyFollowLink(srckey, 0, 1, statret);
02710 }
02711
02712