00001 #include "jsoc_main.h"
00002
00003 char *module_name = "jsoc_export_clone";
00004
00005 typedef enum
00006 {
00007 kExpCloneErr_Success = 0,
00008 kExpCloneErr_Argument,
00009 kExpCloneErr_UnknownSeries,
00010 kExpCloneErr_OutOfMemory,
00011 kExpCloneErr_NoTemplate,
00012 kExpCloneErr_CantCreateProto,
00013 kExpCloneErr_CantCreateSeries,
00014 kExpCloneErr_CantParseKeyDesc,
00015 kExpCloneErr_LibDRMS,
00016 kExpCloneErr_CantFollowLink,
00017 kExpCloneErr_CantChangeWCS
00018 } ExpError_t;
00019
00020 #define kArgSeriesIn "dsin"
00021 #define kArgSeriesOut "dsout"
00022 #define kArgRetention "ret"
00023 #define kArgArchive "arch"
00024 #define kNotSpec "NOTSPECIFIED"
00025
00026
00027 #define kKeyReqID "RequestID"
00028 #define kKeyHistory "HISTORY"
00029 #define kKeyComment "COMMENT"
00030 #define kKeySource "SOURCE"
00031
00032 ModuleArgs_t module_args[] =
00033 {
00034 {ARG_STRING, kArgSeriesIn, NULL, "Input series name."},
00035 {ARG_STRING, kArgSeriesOut, kNotSpec, "(Optional) Output series name."},
00036 {ARG_INT, kArgRetention, "10", "(Optional) Output-series' SU retention."},
00037 {ARG_STRING, kArgArchive, "-1", "(Optional) Output-series' SU archive flag."},
00038 {ARG_END, NULL, NULL, NULL}
00039 };
00040
00041 static DRMS_Record_t *CopySeriesTemplate(DRMS_Env_t *env, const char *in, ExpError_t *status)
00042 {
00043 ExpError_t err = kExpCloneErr_Success;
00044 int drmsstat = DRMS_SUCCESS;
00045
00046 DRMS_Record_t *proto = NULL;
00047 DRMS_Record_t *template = NULL;
00048
00049
00050 if (!drms_series_exists(env, in, &drmsstat) || drmsstat)
00051 {
00052 fprintf(stderr, "Input series '%s' does not exist.\n", in);
00053 err = kExpCloneErr_UnknownSeries;
00054 }
00055 else
00056 {
00057
00058 template = drms_template_record(env, in, &drmsstat);
00059
00060 if (!template || drmsstat)
00061 {
00062 fprintf(stderr, "Unable to obtain template record for series '%s'.\n", in);
00063 err = kExpCloneErr_NoTemplate;
00064 }
00065 else
00066 {
00067
00068 proto = drms_create_recproto(template, &drmsstat);
00069 }
00070
00071 if (!proto || drmsstat)
00072 {
00073 fprintf(stderr, "Unable to obtain record prototype for series '%s'.\n", in);
00074 err = kExpCloneErr_CantCreateProto;
00075 }
00076 }
00077
00078 if (status)
00079 {
00080 *status = err;
00081 }
00082
00083 return proto;
00084 }
00085
00086
00087 static ExpError_t VariableKey(const char*keyname, DRMS_Record_t *prototype)
00088 {
00089 ExpError_t rv = kExpCloneErr_Success;
00090 int drmsstat = DRMS_SUCCESS;
00091 DRMS_Keyword_t *tKey = drms_keyword_lookup(prototype, keyname, 0);
00092 if (tKey)
00093 {
00094 if (tKey->info->recscope == kRecScopeType_Variable || tKey->info->recscope == kRecScopeType_Constant)
00095 {
00096 tKey->info->recscope = kRecScopeType_Variable;
00097 return(rv);
00098 }
00099 else
00100 return(kExpCloneErr_CantChangeWCS);
00101 }
00102 return(rv);
00103 }
00104
00105 static ExpError_t AddAKey(const char *keyname,
00106 DRMS_Record_t *prototype,
00107 const char *desc,
00108 int intprime,
00109 int extprime,
00110 int implicit,
00111 int rank)
00112 {
00113 ExpError_t rv = kExpCloneErr_Success;
00114 int drmsstat = DRMS_SUCCESS;
00115
00116 if (!drms_keyword_lookup(prototype, keyname, 0))
00117 {
00118 DRMS_Keyword_t *tKey = NULL;
00119 DRMS_Keyword_t finalkey;
00120 HContainer_t *keys = NULL;
00121 HIterator_t *hit = NULL;
00122
00123 keys = drms_parse_keyworddesc(prototype->env, desc, &drmsstat);
00124 if (!keys || drmsstat)
00125 {
00126 fprintf(stderr, "Failed to parse keyword description '%s'.\n", desc);
00127 rv = kExpCloneErr_CantParseKeyDesc;
00128 }
00129 else if (hcon_size(keys) == 1)
00130 {
00131
00132 hit = hiter_create(keys);
00133
00134 if (hit)
00135 {
00136 tKey = (DRMS_Keyword_t *)hiter_getnext(hit);
00137 tKey->record = prototype;
00138
00139
00140 tKey->info->rank = rank;
00141 tKey->info->kwflags |= (rank + 1) << 16;
00142
00143
00144 if (intprime)
00145 {
00146 drms_keyword_setintprime(tKey);
00147 }
00148
00149 if (extprime)
00150 {
00151 drms_keyword_setextprime(tKey);
00152 }
00153
00154 if (implicit)
00155 {
00156 drms_keyword_setimplicit(tKey);
00157 }
00158
00159
00160
00161
00162
00163 finalkey.record = tKey->record;
00164 finalkey.info = malloc(sizeof(DRMS_KeywordInfo_t));
00165 *(finalkey.info) = *(tKey->info);
00166 finalkey.value = tKey->value;
00167
00168
00169
00170
00171 hcon_insert_lower(&prototype->keywords, keyname, &finalkey);
00172
00173 if (intprime)
00174 {
00175
00176 tKey = (DRMS_Keyword_t *)hcon_lookup_lower(&prototype->keywords, keyname);
00177 if (tKey)
00178 {
00179 prototype->seriesinfo->pidx_keywords[prototype->seriesinfo->pidx_num++] = tKey;
00180 }
00181 else
00182 {
00183 rv = kExpCloneErr_LibDRMS;
00184 }
00185 }
00186
00187 hiter_destroy(&hit);
00188 }
00189 }
00190 else
00191 {
00192
00193 fprintf(stderr, "Failed to parse keyword description '%s'.\n", desc);
00194 rv = kExpCloneErr_CantParseKeyDesc;
00195 }
00196
00197 if (keys)
00198 {
00199
00200
00201 hcon_destroy(&keys);
00202 }
00203 }
00204
00205 return rv;
00206 }
00207
00208 int DoIt(void)
00209 {
00210 ExpError_t err = kExpCloneErr_Success;
00211
00212 int drmsstat = DRMS_SUCCESS;
00213 char *seriesin = NULL;
00214 const char *seriesout = NULL;
00215 char *name = NULL;
00216 int retention = -1;
00217 int archive = -1;
00218 DRMS_Record_t *copy = NULL;
00219 DRMS_Segment_t *seg = NULL;
00220 HIterator_t *lastseg = NULL;
00221 int hirank = -1;
00222 int exists = 0;
00223
00224
00225 seriesin = strdup(cmdparams_get_str(&cmdparams, kArgSeriesIn, NULL));
00226
00227
00228 seriesout = cmdparams_get_str(&cmdparams, kArgSeriesOut, NULL);
00229
00230 if (strcmp(seriesout, kNotSpec) == 0)
00231 {
00232
00233
00234 size_t nsize = strlen(seriesin) + 16;
00235 name = calloc(nsize, 1);
00236 name = base_strcatalloc(name, seriesin, &nsize);
00237 name = base_strcatalloc(name, "_mod", &nsize);
00238 }
00239 else
00240 {
00241 name = strdup(seriesout);
00242 }
00243
00244 exists = drms_series_exists(drms_env, name, &drmsstat);
00245
00246 if (drmsstat && drmsstat != DRMS_ERROR_UNKNOWNSERIES)
00247 {
00248 fprintf(stderr, "Unable to check for series '%s' existence; bailing out.\n", name);
00249 err = kExpCloneErr_LibDRMS;
00250 }
00251 else if (!exists)
00252 {
00253
00254 retention = cmdparams_get_int(&cmdparams, kArgRetention, NULL);
00255
00256
00257 archive = cmdparams_get_int(&cmdparams, kArgArchive, NULL);
00258
00259
00260 copy = CopySeriesTemplate(drms_env, seriesin, &err);
00261
00262 if (!copy || err)
00263 {
00264 fprintf(stderr, "Unable to copy template record for series '%s'.\n", seriesin);
00265 if (!err)
00266 {
00267 err = kExpCloneErr_CantCreateProto;
00268 }
00269 }
00270 else
00271 {
00272
00273
00274 snprintf(copy->seriesinfo->seriesname, sizeof(copy->seriesinfo->seriesname), "%s", name);
00275
00276
00277
00278
00279 copy->seriesinfo->archive = archive;
00280 copy->seriesinfo->retention = retention;
00281
00282 hirank = drms_series_gethighestkeyrank(drms_env, seriesin, &drmsstat);
00283 if (drmsstat || hirank == -1)
00284 {
00285 hirank = 0;
00286 }
00287
00288
00289 err = AddAKey(kKeyReqID,
00290 copy,
00291 "Keyword:RequestID, string, variable, record, \"NA\", %s, NA, \"The export request identifier, if this record was inserted while an export was being processed.\"",
00292 1,
00293 1,
00294 0,
00295 1 + hirank++);
00296
00297
00298 if (err == kExpCloneErr_Success)
00299 {
00300 err = AddAKey(kKeyHistory,
00301 copy,
00302 "Keyword:HISTORY, string, variable, record, \"No history\", %s, NA, \"The processing history of the data.\"",
00303 0,
00304 0,
00305 0,
00306 1 + hirank++);
00307 }
00308
00309 if (err == kExpCloneErr_Success)
00310 {
00311 err = AddAKey(kKeyComment,
00312 copy,
00313 "Keyword:COMMENT, string, variable, record, \"No comment\", %s, NA, \"Commentary on the data processing.\"",
00314 0,
00315 0,
00316 0,
00317 1 + hirank++);
00318 }
00319
00320 if (err == kExpCloneErr_Success)
00321 {
00322 err = AddAKey(kKeySource,
00323 copy,
00324 "Keyword:SOURCE, string, variable, record, \"No source\", %s, NA, \"Input record record-set specification.\"",
00325 0,
00326 0,
00327 0,
00328 1 + hirank++);
00329 }
00330
00331
00332 if (err == kExpCloneErr_Success) err = VariableKey("CTYPE1", copy);
00333 if (err == kExpCloneErr_Success) err = VariableKey("CTYPE2", copy);
00334 if (err == kExpCloneErr_Success) err = VariableKey("CUNIT1", copy);
00335 if (err == kExpCloneErr_Success) err = VariableKey("CUNIT2", copy);
00336 if (err == kExpCloneErr_Success) err = VariableKey("CDELT1", copy);
00337 if (err == kExpCloneErr_Success) err = VariableKey("CDELT2", copy);
00338 if (err == kExpCloneErr_Success) err = VariableKey("CRVAL1", copy);
00339 if (err == kExpCloneErr_Success) err = VariableKey("CRVAL2", copy);
00340 if (err == kExpCloneErr_Success) err = VariableKey("CROTA2", copy);
00341 if (err == kExpCloneErr_Success) err = VariableKey("WCSNAME", copy);
00342
00343
00344 if (err == kExpCloneErr_Success) err = VariableKey("DATASIGN", copy);
00345
00346
00347 if (err == kExpCloneErr_Success)
00348 {
00349 DRMS_Link_t *link = NULL;
00350 DRMS_Record_t *tRec = NULL;
00351 DRMS_Segment_t *tSeg = NULL;
00352 char oSegName[DRMS_MAXSEGNAMELEN];
00353 int segnum = 0;
00354 char segkeybuf[512];
00355 char segkeyname[DRMS_MAXKEYNAMELEN];
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 while ((seg = drms_record_nextseg(copy, &lastseg, 0)))
00367 {
00368
00369 if (seg->info->islink)
00370 {
00371
00372
00373 link = hcon_lookup_lower(©->links, seg->info->linkname);
00374
00375 if (!link)
00376 {
00377 fprintf(stderr, "Unable to obtain link %s.\n", seg->info->linkname);
00378 err = kExpCloneErr_CantFollowLink;
00379 break;
00380 }
00381 else
00382 {
00383 tRec = drms_template_record(drms_env, link->info->target_series, &drmsstat);
00384
00385 if (drmsstat != DRMS_SUCCESS || !tRec)
00386 {
00387 fprintf(stderr, "Unable to obtain template record for series %s.\n", link->info->target_series);
00388 err = kExpCloneErr_LibDRMS;
00389 break;
00390 }
00391 else
00392 {
00393 tSeg = drms_segment_lookup(tRec, seg->info->target_seg);
00394
00395 if (!tSeg)
00396 {
00397 fprintf(stderr, "Unable to follow link to target segment.\n");
00398 err = kExpCloneErr_CantFollowLink;
00399 break;
00400 }
00401
00402
00403
00404 snprintf(oSegName, sizeof(oSegName), "%s", seg->info->name);
00405
00406
00407
00408 segnum = seg->info->segnum;
00409
00410
00411 if (seg->info)
00412 {
00413 free(seg->info);
00414 }
00415
00416 *seg = *tSeg;
00417 seg->info = malloc(sizeof(DRMS_SegmentInfo_t));
00418
00419 if (!seg->info)
00420 {
00421 err = kExpCloneErr_OutOfMemory;
00422 break;
00423 }
00424 else
00425 {
00426 *seg->info = *tSeg->info;
00427
00428
00429
00430 seg->record = copy;
00431
00432
00433 snprintf(seg->info->name, sizeof(seg->info->name), "%s", oSegName);
00434 seg->info->segnum = segnum;
00435 }
00436 }
00437 }
00438
00439
00440
00441
00442 if (err == kExpCloneErr_Success)
00443 {
00444 snprintf(segkeyname, sizeof(segkeyname), "%s_bzero", seg->info->name);
00445 snprintf(segkeybuf, sizeof(segkeybuf), "Keyword:%s, double, variable, record, %f, %%g, none, \"\"", segkeyname, seg->bzero);
00446 err = AddAKey(segkeyname,
00447 copy,
00448 segkeybuf,
00449 0,
00450 0,
00451 1,
00452 1 + hirank++);
00453 }
00454
00455 if (err == kExpCloneErr_Success)
00456 {
00457 snprintf(segkeyname, sizeof(segkeyname), "%s_bscale", seg->info->name);
00458 snprintf(segkeybuf, sizeof(segkeybuf), "Keyword:%s, double, variable, record, %f, %%g, none, \"\"", segkeyname, seg->bscale);
00459 err = AddAKey(segkeyname,
00460 copy,
00461 segkeybuf,
00462 0,
00463 0,
00464 1,
00465 1 + hirank++);
00466 }
00467
00468 if (err == kExpCloneErr_Success)
00469 {
00470 snprintf(segkeyname, sizeof(segkeyname), "cparms_sg%03d", seg->info->segnum);
00471 snprintf(segkeybuf, sizeof(segkeybuf), "Keyword:%s, string, variable, record, \"%s\", %%s, none, \"\"", segkeyname, seg->cparms);
00472 err = AddAKey(segkeyname,
00473 copy,
00474 segkeybuf,
00475 0,
00476 0,
00477 1,
00478 1 + hirank++);
00479 }
00480
00481 }
00482
00483 if (seg->info->protocol == DRMS_FITS)
00484 {
00485 if (seg->info->scope != DRMS_VARDIM)
00486 {
00487 seg->info->scope = DRMS_VARDIM;
00488 memset(seg->axis, 0, sizeof(seg->axis));
00489 }
00490 }
00491 }
00492
00493 if (lastseg)
00494 {
00495 hiter_destroy(&lastseg);
00496 }
00497
00498
00499
00500 }
00501
00502 if (err == kExpCloneErr_Success)
00503 {
00504 DRMS_Keyword_t *key = NULL;
00505 DRMS_Link_t *link = NULL;
00506 DRMS_Record_t *tRec = NULL;
00507 DRMS_Keyword_t *tKey = NULL;
00508 HIterator_t *lastkey = NULL;
00509 char oKeyName[DRMS_MAXKEYNAMELEN];
00510 int rank = -1;
00511
00512
00513 while ((key = drms_record_nextkey(copy, &lastkey, 0)))
00514 {
00515
00516 if (key->info->islink)
00517 {
00518
00519
00520 link = hcon_lookup_lower(©->links, key->info->linkname);
00521
00522 if (!link)
00523 {
00524 fprintf(stderr, "Unable to obtain link %s.\n", key->info->linkname);
00525 err = kExpCloneErr_CantFollowLink;
00526 break;
00527 }
00528 else
00529 {
00530 tRec = drms_template_record(drms_env, link->info->target_series, &drmsstat);
00531
00532 if (drmsstat != DRMS_SUCCESS || !tRec)
00533 {
00534 fprintf(stderr, "Unable to obtain template record for series %s.\n", link->info->target_series);
00535 err = kExpCloneErr_LibDRMS;
00536 break;
00537 }
00538 else
00539 {
00540 tKey = drms_keyword_lookup(tRec, key->info->target_key, 0);
00541
00542 if (!tKey)
00543 {
00544 fprintf(stderr, "Unable to follow link to target keyword.\n");
00545 err = kExpCloneErr_CantFollowLink;
00546 break;
00547 }
00548
00549
00550
00551 snprintf(oKeyName, sizeof(oKeyName), "%s", key->info->name);
00552
00553
00554
00555 rank = key->info->rank;
00556
00557
00558
00559
00560
00561 if (key->info->type == DRMS_TYPE_STRING && key->value.string_val)
00562 {
00563 free(key->value.string_val);
00564 key->value.string_val = NULL;
00565 }
00566
00567 if (key->info)
00568 {
00569 free(key->info);
00570 }
00571
00572 *key = *tKey;
00573 key->info = malloc(sizeof(DRMS_KeywordInfo_t));
00574
00575 if (!key->info)
00576 {
00577 err = kExpCloneErr_OutOfMemory;
00578 break;
00579 }
00580 else
00581 {
00582 *key->info = *tKey->info;
00583
00584
00585
00586 key->record = copy;
00587
00588
00589 snprintf(key->info->name, sizeof(key->info->name), "%s", oKeyName);
00590 key->info->rank = rank;
00591 }
00592
00593 if (key->info->type == DRMS_TYPE_STRING)
00594 {
00595 key->value.string_val = strdup(tKey->value.string_val);
00596 }
00597 }
00598 }
00599 }
00600 }
00601
00602 if (lastkey)
00603 {
00604 hiter_destroy(&lastkey);
00605 }
00606 }
00607
00608 if (err == kExpCloneErr_Success)
00609 {
00610
00611 (copy->links).deep_free = (void (*)(const void *)) drms_free_template_link_struct;
00612 hcon_free(©->links);
00613 }
00614
00615 if (err == kExpCloneErr_Success)
00616 {
00617
00618
00619 if (drms_create_series_fromprototype(©, name, 0))
00620 {
00621 err = kExpCloneErr_CantCreateSeries;
00622 }
00623 }
00624 }
00625 }
00626
00627
00628 if (copy)
00629 {
00630
00631 drms_destroy_recproto(©);
00632 }
00633
00634 if (name)
00635 {
00636 free(name);
00637 }
00638
00639 if (seriesin)
00640 {
00641 free(seriesin);
00642 }
00643
00644 return err;
00645 }