00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "drms.h"
00033 #include "drms_priv.h"
00034 #include <float.h>
00035 #include <dlfcn.h>
00036 #include "xmem.h"
00037 #include "drms_dsdsapi.h"
00038 #include "cfitsio.h"
00039 #include "fitsexport.h"
00040
00041
00042
00043 static DRMS_Segment_t * __drms_segment_lookup(DRMS_Record_t *rec,
00044 const char *segname, int depth);
00045
00046 static int drms_segment_set_const(DRMS_Segment_t *seg);
00047 static int drms_segment_checkscaling (const DRMS_Array_t* arr, double bzero,
00048 double bscale);
00049
00050
00051
00052
00053
00054
00055
00056
00057 static DRMS_Segment_t * __drms_segment_lookup(DRMS_Record_t *rec,
00058 const char *segname, int depth)
00059 {
00060 int stat;
00061 DRMS_Segment_t *segment;
00062 DRMS_Segment_t *rv = NULL;
00063
00064 segment = hcon_lookup_lower(&rec->segments, segname);
00065 if (segment!=NULL && depth<DRMS_MAXLINKDEPTH )
00066 {
00067 if (segment->info->islink)
00068 {
00069 DRMS_Record_t *linkedRec = NULL;
00070
00071 linkedRec = drms_link_follow(rec, segment->info->linkname, &stat);
00072 if (stat)
00073 rv = NULL;
00074 else
00075 {
00076 rv = __drms_segment_lookup(linkedRec, segment->info->target_seg, depth+1);
00077 }
00078
00079
00080
00081
00082 return rv;
00083
00084 }
00085 else
00086 {
00087 return segment;
00088 }
00089 }
00090 if (depth>=DRMS_MAXLINKDEPTH)
00091 fprintf(stderr, "WARNING: Max link depth exceeded for segment '%s' in "
00092 "record %lld from series '%s'\n", segment->info->name, rec->recnum,
00093 rec->seriesinfo->seriesname);
00094
00095 return NULL;
00096 }
00097
00098 int drms_segment_set_const(DRMS_Segment_t *seg) {
00099 XASSERT(seg->info->scope == DRMS_CONSTANT &&
00100 !seg->info->cseg_recnum);
00101 DRMS_Record_t *rec = seg->record;
00102 seg->info->cseg_recnum = rec->recnum;
00103
00104
00105 char stmt[DRMS_MAXQUERYLEN];
00106 char *namespace = ns(rec->seriesinfo->seriesname);
00107 char *lcseries = strdup(rec->seriesinfo->seriesname);
00108
00109 if (!lcseries)
00110 {
00111 free(namespace);
00112 return DRMS_ERROR_OUTOFMEMORY;
00113 }
00114
00115 char *lcsegname = strdup(seg->info->name);
00116
00117 if (!lcsegname)
00118 {
00119 free(lcseries);
00120 free(namespace);
00121 return DRMS_ERROR_OUTOFMEMORY;
00122 }
00123
00124 strtolower(lcseries);
00125 strtolower(lcsegname);
00126
00127 sprintf(stmt, "UPDATE %s." DRMS_MASTER_SEGMENT_TABLE
00128 " SET cseg_recnum = %lld WHERE lower(seriesname) = '%s' AND lower(segmentname) = '%s'",
00129 namespace, rec->recnum, lcseries, lcsegname);
00130
00131 free(lcsegname);
00132 free(lcseries);
00133 free(namespace);
00134
00135 if(drms_dms(rec->env->session, NULL, stmt)) {
00136 fprintf(stderr, "Failed to update drms_segment table for constant segment\n");
00137 return DRMS_ERROR_QUERYFAILED;
00138 }
00139 return DRMS_SUCCESS;
00140 }
00141
00142 int drms_segment_checkscaling (const DRMS_Array_t *a, double zero, double scale) {
00143 int ret = 1;
00144 double numz = fabs (a->bzero - zero);
00145 double nums = fabs (a->bscale - scale);
00146 double denz = fabs (zero);
00147 double dens = fabs (scale);
00148
00149 denz += fabs (a->bzero);
00150 dens += fabs (a->bscale);
00151
00152 if ((numz > 1.0e-11 * denz) || (nums > 1.0e-11 * dens)) {
00153 ret = 0;
00154 }
00155 return ret;
00156 }
00157
00158
00159 void drms_free_template_segment_struct (DRMS_Segment_t *segment) {
00160 free (segment->info);
00161 }
00162
00163 void drms_free_segment_struct (DRMS_Segment_t *segment) {
00164 XASSERT(segment);
00165 return;
00166 }
00167
00168 void drms_copy_segment_struct(DRMS_Segment_t *dst, DRMS_Segment_t *src)
00169 {
00170
00171 memcpy(dst,src,sizeof(DRMS_Segment_t));
00172 return;
00173 }
00174
00175
00176 HContainer_t *drms_create_segment_prototypes(DRMS_Record_t *target,
00177 DRMS_Record_t *source,
00178 int *status)
00179 {
00180 HContainer_t *ret = NULL;
00181 DRMS_Segment_t *tSeg = NULL;
00182 DRMS_Segment_t *sSeg = NULL;
00183
00184 XASSERT(target != NULL && target->segments.num_total == 0 && source != NULL);
00185
00186 if (target != NULL && target->segments.num_total == 0 && source != NULL)
00187 {
00188 *status = DRMS_SUCCESS;
00189 HIterator_t hit;
00190 hiter_new_sort(&hit, &(source->segments), drms_segment_ranksort);
00191
00192 while ((sSeg = hiter_getnext(&hit)) != NULL)
00193 {
00194 if (sSeg->info && strlen(sSeg->info->name) > 0)
00195 {
00196 tSeg = hcon_allocslot_lower(&(target->segments), sSeg->info->name);
00197 XASSERT(tSeg);
00198 memset(tSeg, 0, sizeof(DRMS_Segment_t));
00199 tSeg->info = malloc(sizeof(DRMS_SegmentInfo_t));
00200 XASSERT(tSeg->info);
00201 memset(tSeg->info, 0, sizeof(DRMS_SegmentInfo_t));
00202
00203 if (tSeg && tSeg->info)
00204 {
00205
00206 tSeg->record = target;
00207
00208
00209 memcpy(tSeg->info, sSeg->info, sizeof(DRMS_SegmentInfo_t));
00210
00211
00212 memcpy(tSeg->axis, sSeg->axis, sizeof(int) * DRMS_MAXRANK);
00213
00214 if (tSeg->info->protocol == DRMS_TAS)
00215 {
00216
00217 memcpy(tSeg->blocksize, sSeg->blocksize, sizeof(int) * DRMS_MAXRANK);
00218 }
00219
00220
00221 snprintf(tSeg->cparms, sizeof(tSeg->cparms), "%s", sSeg->cparms);
00222
00223
00224 tSeg->bzero = sSeg->bzero;
00225 tSeg->bscale = sSeg->bscale;
00226 }
00227 else
00228 {
00229 *status = DRMS_ERROR_OUTOFMEMORY;
00230 }
00231 }
00232 else
00233 {
00234 *status = DRMS_ERROR_INVALIDSEGMENT;
00235 }
00236 }
00237
00238 hiter_free(&hit);
00239
00240 if (*status == DRMS_SUCCESS)
00241 {
00242 ret = &(target->segments);
00243 }
00244 }
00245 else
00246 {
00247 *status = DRMS_ERROR_INVALIDRECORD;
00248 }
00249
00250 return ret;
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 int drms_template_segments(DRMS_Record_t *template)
00261 {
00262 DRMS_Env_t *env;
00263 int i,n,status = DRMS_NO_ERROR;
00264 char buf[1024], query[DRMS_MAXQUERYLEN], *p, *q;
00265 DRMS_Segment_t *seg;
00266 DB_Binary_Result_t *qres;
00267 char *lcseries = strdup(template->seriesinfo->seriesname);
00268
00269 if (!lcseries)
00270 {
00271 status = DRMS_ERROR_OUTOFMEMORY;
00272 goto bailout;
00273 }
00274
00275 strtolower(lcseries);
00276
00277 env = template->env;
00278
00279
00280 hcon_init(&template->segments, sizeof(DRMS_Segment_t), DRMS_MAXSEGNAMELEN,
00281 (void (*)(const void *)) drms_free_segment_struct,
00282 (void (*)(const void *, const void *)) drms_copy_segment_struct);
00283
00284
00285 char *namespace = ns(template->seriesinfo->seriesname);
00286 sprintf(query, "select segmentname, segnum, scope, type, "
00287 "naxis, axis, unit, protocol, description, "
00288 "islink, linkname, targetseg, cseg_recnum from %s.%s where "
00289 "lower(seriesname) = '%s' order by segnum",
00290 namespace, DRMS_MASTER_SEGMENT_TABLE, lcseries);
00291 free(lcseries);
00292 free(namespace);
00293
00294 if (env->verbose)
00295 {
00296 fprintf(stdout, "Template Segment Query: %s\n", query);
00297 }
00298
00299 if ((qres = drms_query_bin(env->session, query)) == NULL)
00300 return DRMS_ERROR_QUERYFAILED;
00301
00302 #ifdef DEBUG
00303 printf("#0\n");
00304 db_print_binary_result(qres);
00305 #endif
00306
00307 if (qres->num_rows>0 && qres->num_cols != 13 )
00308 {
00309 status = DRMS_ERROR_BADFIELDCOUNT;
00310 goto bailout;
00311 }
00312 for (i = 0; i<(int)qres->num_rows; i++)
00313 {
00314
00315 db_binary_field_getstr(qres, i, 0, 1024, buf);
00316 seg = hcon_allocslot_lower(&template->segments, buf);
00317 memset(seg,0,sizeof(DRMS_Segment_t));
00318 seg->info = malloc(sizeof( DRMS_SegmentInfo_t));
00319 XASSERT(seg->info);
00320 memset(seg->info,0,sizeof(DRMS_SegmentInfo_t));
00321 seg->record = template;
00322 strcpy(seg->info->name, buf);
00323
00324 seg->info->segnum = db_binary_field_getint(qres, i, 1);
00325 seg->info->islink = db_binary_field_getint(qres, i, 9);
00326 if (seg->info->islink) {
00327
00328 db_binary_field_getstr(qres, i, 10, sizeof(seg->info->linkname),seg->info->linkname);
00329 db_binary_field_getstr(qres, i, 11, sizeof(seg->info->target_seg),seg->info->target_seg);
00330 seg->info->scope = DRMS_VARIABLE;
00331 seg->info->type = DRMS_TYPE_INT;
00332 seg->info->unit[0] = '\0';
00333 seg->info->protocol = DRMS_GENERIC;
00334 } else {
00335
00336
00337 db_binary_field_getstr(qres, i, 2, 1024, buf);
00338 seg->info->cseg_recnum = 0;
00339 if (!strcmp(buf, "constant")) {
00340 seg->info->scope = DRMS_CONSTANT;
00341 seg->info->cseg_recnum = db_binary_field_getlonglong(qres, i, 12);
00342 }
00343 else if (!strcmp(buf, "variable"))
00344 seg->info->scope = DRMS_VARIABLE;
00345 else if (!strcmp(buf, "vardim"))
00346 seg->info->scope = DRMS_VARDIM;
00347 else
00348 {
00349 printf("ERROR: Invalid segment scope specifier '%s'\n",buf);
00350 goto bailout;
00351 }
00352
00353 db_binary_field_getstr(qres, i, 3, 1024,buf);
00354 seg->info->type = drms_str2type(buf);
00355
00356 db_binary_field_getstr(qres, i, 6, DRMS_MAXUNITLEN, seg->info->unit);
00357
00358 db_binary_field_getstr(qres, i, 7, 1024, buf);
00359 seg->info->protocol = drms_str2prot(buf);
00360 }
00361
00362 seg->info->naxis = db_binary_field_getint(qres, i, 4);
00363
00364 db_binary_field_getstr(qres, i, 5, 1024,buf);
00365 n = 0;
00366 p = buf;
00367
00368
00369 while(*p)
00370 {
00371 XASSERT(n<2*seg->info->naxis);
00372 while(!isdigit(*p))
00373 ++p;
00374 q = p;
00375 while(isdigit(*p))
00376 ++p;
00377 *p++ = 0;
00378 if (n<seg->info->naxis)
00379 seg->axis[n] = atoi(q);
00380 else
00381 seg->blocksize[n - seg->info->naxis] = atoi(q);
00382 n++;
00383 }
00384 if (seg->info->protocol!=DRMS_TAS)
00385 {
00386 XASSERT(n==seg->info->naxis);
00387 memcpy(seg->blocksize,seg->axis,n*sizeof(int));
00388 }
00389 else
00390 {
00391 XASSERT(n==2*seg->info->naxis);
00392 }
00393
00394
00395 seg->filename[0] = '\0';
00396
00397 db_binary_field_getstr(qres, i, 8, DRMS_MAXCOMMENTLEN, seg->info->description);
00398 }
00399 #ifdef DEBUG
00400 printf("#4\n");
00401 db_print_binary_result(qres);
00402 #endif
00403 db_free_binary_result(qres);
00404 return DRMS_SUCCESS;
00405
00406 bailout:
00407 db_free_binary_result(qres);
00408 return status;
00409 }
00410
00411
00412
00413
00414 void drms_segment_print(DRMS_Segment_t *seg)
00415 {
00416 drms_segment_fprint(stdout, seg);
00417 }
00418
00419
00420
00421 void drms_segment_fprint(FILE *keyfile, DRMS_Segment_t *seg)
00422 {
00423 int i;
00424 const int fieldwidth=13;
00425
00426 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "name", seg->info->name);
00427 fprintf(keyfile, "\t%-*s:\t%d\n", fieldwidth, "segnum", seg->info->segnum);
00428 fprintf(keyfile, "\t%-*s:\t%s\n", fieldwidth, "description", seg->info->description);
00429 if (seg->info->islink) {
00430 fprintf(keyfile, "\t%-*s:\t%s\n", fieldwidth, "linkname", seg->info->linkname);
00431 fprintf(keyfile, "\t%-*s:\t%s\n", fieldwidth, "target segment", seg->info->target_seg);
00432 } else {
00433 switch(seg->info->scope)
00434 {
00435 case DRMS_CONSTANT:
00436 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "scope", "CONSTANT");
00437 break;
00438 case DRMS_VARIABLE:
00439 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "scope", "VARIABLE");
00440 break;
00441 case DRMS_VARDIM:
00442 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "scope", "VARIABLE DIMENSION");
00443 break;
00444 default:
00445 fprintf(keyfile, "\t%-*s:\t%s %d\n", fieldwidth, "scope", "Illegal value",
00446 (int)seg->info->scope);
00447 }
00448 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "unit", seg->info->unit);
00449 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth+9, "type",
00450 drms_type2str(seg->info->type));
00451
00452
00453 const char *protstr = drms_prot2str(seg->info->protocol);
00454 if (protstr)
00455 {
00456 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "protocol", protstr);
00457 }
00458 else
00459 {
00460 fprintf(keyfile, "\t%-*s:\t%s %d\n", fieldwidth, "protocol", "Illegal value",
00461 (int)seg->info->protocol);
00462 }
00463
00464 if (strlen(seg->filename)) {
00465 fprintf(keyfile, "\t%-*s:\t'%s'\n", fieldwidth, "filename", seg->filename);
00466 }
00467 }
00468
00469 fprintf(keyfile, "\t%-*s:\t%d\n", fieldwidth+9, "naxis", seg->info->naxis);
00470 for (i=0; i<seg->info->naxis; i++)
00471 {
00472 fprintf(keyfile, "\t%-*s[%2d]:\t%d\n", fieldwidth+5, "axis", i,
00473 seg->axis[i]);
00474 }
00475
00476 }
00477
00478
00479
00480 long long drms_segment_size(DRMS_Segment_t *seg, int *status)
00481 {
00482 int i;
00483 long long size;
00484
00485 size = 1;
00486 for (i=0; i<seg->info->naxis; i++)
00487 size *= seg->axis[i];
00488 if (seg->info->type == DRMS_TYPE_STRING)
00489 size = size*sizeof(char *);
00490 else
00491 size *= drms_sizeof(seg->info->type);
00492 if (status)
00493 *status = DRMS_SUCCESS;
00494 return size;
00495 }
00496
00497 int drms_segment_setdims(DRMS_Segment_t *seg, DRMS_SegmentDimInfo_t *di)
00498 {
00499 int status = DRMS_SUCCESS;
00500
00501 if (seg && di)
00502 {
00503 seg->info->naxis = di->naxis;
00504 memcpy(seg->axis, di->axis, sizeof(int) * di->naxis);
00505 }
00506 else
00507 {
00508 status = DRMS_ERROR_INVALIDDATA;
00509 }
00510
00511 return status;
00512 }
00513
00514
00515 int drms_segment_getdims(DRMS_Segment_t *seg, DRMS_SegmentDimInfo_t *di)
00516 {
00517 int status = DRMS_SUCCESS;
00518
00519 if (seg && di)
00520 {
00521 di->naxis = seg->info->naxis;
00522 memcpy(di->axis, seg->axis, sizeof(int) * di->naxis);
00523 }
00524
00525 return status;
00526 }
00527
00528 HContainer_t *drms_segment_createinfocon(DRMS_Env_t *drmsEnv,
00529 const char *seriesName,
00530 int *status)
00531 {
00532 HContainer_t *ret = NULL;
00533
00534 DRMS_Record_t *template = drms_template_record(drmsEnv, seriesName, status);
00535
00536 if (*status == DRMS_SUCCESS)
00537 {
00538 int size = hcon_size(&(template->segments));
00539 if (size > 0)
00540 {
00541 char **nameArr = (char **)malloc(sizeof(char *) * size);
00542 DRMS_SegmentInfo_t **valArr =
00543 (DRMS_SegmentInfo_t **)malloc(sizeof(DRMS_SegmentInfo_t *) * size);
00544
00545 if (nameArr != NULL && valArr != NULL)
00546 {
00547 HIterator_t hit;
00548 hiter_new_sort(&hit, &(template->segments), drms_segment_ranksort);
00549 DRMS_Segment_t *seg = NULL;
00550
00551 int iSeg = 0;
00552 while ((seg = hiter_getnext(&hit)) != NULL)
00553 {
00554 nameArr[iSeg] = seg->info->name;
00555 valArr[iSeg] = seg->info;
00556
00557 iSeg++;
00558 }
00559
00560 ret = hcon_create(sizeof(DRMS_SegmentInfo_t),
00561 DRMS_MAXSEGNAMELEN,
00562 NULL,
00563 NULL,
00564 (void **)valArr,
00565 nameArr,
00566 size);
00567 }
00568 else
00569 {
00570 *status = DRMS_ERROR_OUTOFMEMORY;
00571 }
00572
00573 if (nameArr != NULL)
00574 {
00575 free(nameArr);
00576 }
00577
00578 if (valArr != NULL)
00579 {
00580 free(valArr);
00581 }
00582 }
00583 }
00584
00585 return ret;
00586 }
00587
00588 void drms_segment_destroyinfocon(HContainer_t **info)
00589 {
00590 hcon_destroy(info);
00591 }
00592
00593
00594
00595
00596
00597
00598 void drms_segment_filename(DRMS_Segment_t *seg, char *filename)
00599 {
00600 int statint;
00601
00602 if (seg->info->protocol == DRMS_DSDS)
00603 {
00604
00605
00606 if (strlen(seg->filename) > 0)
00607 {
00608 snprintf(filename, DRMS_MAXPATHLEN, "%s", seg->filename);
00609 }
00610 else if (filename)
00611 {
00612 *filename = '\0';
00613 }
00614 }
00615 else if (seg->info->protocol != DRMS_LOCAL)
00616 {
00617
00618 DRMS_Record_t *rec = seg->record;
00619
00620 statint = DRMS_SUCCESS;
00621
00622 if (rec->sunum != -1LL && rec->su == NULL)
00623 {
00624
00625 if ((rec->su = drms_getunit(rec->env,
00626 rec->seriesinfo->seriesname,
00627 rec->sunum,
00628 1,
00629 &statint)) == NULL)
00630 {
00631 statint = DRMS_ERROR_NOSTORAGEUNIT;
00632 *(seg->filename) = '\0';
00633 *filename = '\0';
00634 }
00635 else
00636 {
00637 rec->su->refcount++;
00638 }
00639 }
00640
00641 if (statint == DRMS_SUCCESS)
00642 {
00643 if (strlen(seg->filename)) {
00644 if (seg->info->protocol == DRMS_TAS)
00645 CHECKSNPRINTF(snprintf(filename, DRMS_MAXPATHLEN, "%s/%s",
00646 rec->su->sudir, seg->filename), DRMS_MAXPATHLEN);
00647 else
00648 CHECKSNPRINTF(snprintf(filename, DRMS_MAXPATHLEN, "%s/" DRMS_SLOTDIR_FORMAT "/%s",
00649 rec->su->sudir, rec->slotnum, seg->filename), DRMS_MAXPATHLEN);
00650 } else {
00651 if (seg->info->protocol == DRMS_TAS)
00652 {
00653 CHECKSNPRINTF(snprintf(filename, DRMS_MAXPATHLEN, "%s/%s.tas",
00654 rec->su->sudir, seg->info->name), DRMS_MAXPATHLEN);
00655
00656 snprintf(seg->filename, sizeof(seg->filename), "%s.tas", seg->info->name);
00657 }
00658 else
00659 {
00660 CHECKSNPRINTF(snprintf(filename, DRMS_MAXPATHLEN, "%s/" DRMS_SLOTDIR_FORMAT "/%s%s",
00661 rec->su->sudir, rec->slotnum, seg->info->name,
00662 drms_prot2ext(seg->info->protocol)), DRMS_MAXPATHLEN);
00663
00664 snprintf(seg->filename, sizeof(seg->filename), "%s%s", seg->info->name, drms_prot2ext(seg->info->protocol));
00665 }
00666 }
00667 }
00668 }
00669
00670 }
00671
00672
00673 int drms_delete_segmentfile (DRMS_Segment_t *seg) {
00674 char filename[DRMS_MAXPATHLEN];
00675
00676 drms_segment_filename (seg, filename);
00677 if (unlink (filename)) {
00678 perror ("ERROR in drms_delete_segmentfile: unlink failed with");
00679 return DRMS_ERROR_UNLINKFAILED;
00680 } else return DRMS_SUCCESS;
00681 }
00682
00683
00684 DRMS_Segment_t *drms_segment_lookup (DRMS_Record_t *rec, const char *segname) {
00685 DRMS_Segment_t *seg = __drms_segment_lookup (rec, segname, 0);
00686
00687 if (!seg) return NULL;
00688 if (seg->info->scope == DRMS_CONSTANT) {
00689
00690
00691
00692
00693 if (!seg->info->cseg_recnum) {
00694 return seg;
00695 } else {
00696 if (seg->record->recnum == seg->info->cseg_recnum) {
00697 return seg;
00698 } else {
00699 int status = 0;
00700 DRMS_Record_t *rec2 = drms_retrieve_record(rec->env, rec->seriesinfo->seriesname, seg->info->cseg_recnum, NULL, &status);
00701 if (status) {
00702 fprintf(stderr, "Failed to retrieve record for constant segment, recnum = %lld", seg->info->cseg_recnum);
00703 return NULL;
00704 }
00705 return drms_segment_lookup(rec2, segname);
00706 }
00707 }
00708 } else return seg;
00709 }
00710
00711
00712
00713
00714
00715 DRMS_Segment_t *drms_segment_lookupnum(DRMS_Record_t *rec, int segnum)
00716 {
00717 HIterator_t hit;
00718 DRMS_Segment_t *seg = NULL;
00719
00720 hiter_new_sort(&hit, &rec->segments, drms_segment_ranksort);
00721 while ((seg = (DRMS_Segment_t *)hiter_getnext(&hit)) != NULL)
00722 {
00723 if (seg->info->segnum == segnum)
00724 {
00725 break;
00726 }
00727 else if (seg->info->segnum > segnum)
00728 {
00729 seg = NULL;
00730 break;
00731 }
00732 }
00733
00734 if (seg)
00735 {
00736
00737
00738
00739 seg = drms_segment_lookup(rec, seg->info->name);
00740 }
00741
00742 hiter_free(&hit);
00743
00744 return seg;
00745 }
00746
00747 DRMS_Segment_t *drms_segment_lookupindex(DRMS_Record_t *rec, int index, int followLink)
00748 {
00749 HIterator_t hit;
00750 DRMS_Segment_t *seg = NULL;
00751 int count;
00752
00753 if (rec == NULL)
00754 {
00755 return NULL;
00756 }
00757
00758 if (index < 0 || index > drms_record_numsegments(rec) - 1)
00759 {
00760 return NULL;
00761 }
00762
00763 hiter_new_sort(&hit, &rec->segments, drms_segment_ranksort);
00764 for (count = 0; count <= index; count++)
00765 {
00766 seg = (DRMS_Segment_t *)hiter_getnext(&hit);
00767 if (!seg)
00768 {
00769
00770 break;
00771 }
00772 }
00773
00774 if (seg && followLink)
00775 {
00776
00777
00778
00779 seg = drms_segment_lookup(rec, seg->info->name);
00780 }
00781
00782 hiter_free(&hit);
00783
00784 return seg;
00785 }
00786
00787
00788 #if 0
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 void drms_segment_destroy(DRMS_Segment_t *oSeg, DRMS_Segment_t **pSeg)
00804 {
00805 DRMS_Segment_t *seg = NULL;
00806 DRMS_Link_t *link = NULL;
00807 char hashkey[DRMS_MAXHASHKEYLEN];
00808 void *lookup = NULL;
00809 DRMS_Record_t *linkedRec = NULL;
00810
00811 if (oSeg && pSeg && (seg = *pSeg))
00812 {
00813 if (oSeg->record && oSeg->info->islink && *oSeg->info->linkname != '\0')
00814 {
00815 link = hcon_lookup_lower(&oSeg->record->links, oSeg->info->linkname);
00816
00817 if (link)
00818 {
00819 if ((link->info->type == STATIC_LINK && link->recnum != -1) ||
00820 (link->info->type == DYNAMIC_LINK && link->isset))
00821 {
00822
00823 drms_make_hashkey(hashkey, link->info->target_series, link->recnum);
00824 lookup = hcon_lookup_lower(mapRec, hashkey);
00825 if (lookup)
00826 {
00827
00828 linkedRec = *((DRMS_Record_t **)lookup);
00829
00830
00831
00832
00833
00834
00835
00836 if (linkedRec == seg->record)
00837 {
00838 drms_free_record(seg->record);
00839 seg->record = NULL;
00840
00841 *pSeg = NULL;
00842 }
00843 }
00844 }
00845 }
00846 }
00847 }
00848 }
00849 #endif
00850
00851
00852
00853 FILE *drms_segment_fopen(DRMS_Segment_t *seg, const char *newfilename, int append, int *status)
00854 {
00855 FILE *file = NULL;
00856 DRMS_Record_t *rec = NULL;
00857 int statint = DRMS_SUCCESS;
00858 char filename[DRMS_MAXPATHLEN];
00859 char path[DRMS_MAXPATHLEN];
00860
00861 if (seg)
00862 {
00863 rec = seg->record;
00864
00865
00866 if (rec->sunum != -1LL && rec->su == NULL)
00867 {
00868
00869 if ((rec->su = drms_getunit(rec->env,
00870 rec->seriesinfo->seriesname,
00871 rec->sunum,
00872 1,
00873 &statint)) == NULL)
00874 {
00875 statint = DRMS_ERROR_NOSTORAGEUNIT;
00876 }
00877 else
00878 {
00879 rec->su->refcount++;
00880 }
00881 }
00882
00883 if (!statint)
00884 {
00885
00886
00887
00888
00889
00890 struct stat stbuf;
00891
00892 drms_segment_filename(seg, path);
00893
00894 if (rec->su->mode == DRMS_READWRITE && stat(path, &stbuf))
00895 {
00896 char *tmp = strdup(path);
00897 char *pc = strrchr(tmp, '/');
00898 *pc = '\0';
00899 pc++;
00900
00901 if (newfilename)
00902 {
00903 snprintf(filename, sizeof(filename), "%s", newfilename);
00904 snprintf(path, sizeof(path), "%s/%s", tmp, newfilename);
00905 }
00906 else
00907 {
00908
00909 snprintf(filename, sizeof(filename), "%s", pc);
00910 }
00911
00912 CHECKSNPRINTF(snprintf(seg->filename, DRMS_MAXSEGFILENAME, "%s", filename),
00913 DRMS_MAXSEGFILENAME);
00914
00915 free(tmp);
00916 }
00917
00918
00919
00920
00921 if (rec->su->mode == DRMS_READONLY)
00922 {
00923 file = fopen(path, "r");
00924 }
00925 else if (rec->su->mode == DRMS_READWRITE)
00926 {
00927 if (append)
00928 {
00929 file = fopen(path, "a+");
00930 }
00931 else
00932 {
00933 file = fopen(path, "w+");
00934 }
00935 }
00936 else
00937 {
00938 statint = DRMS_ERROR_INVALIDSU;
00939 }
00940
00941 if (!statint && !file)
00942 {
00943 statint = DRMS_ERROR_INVALIDFILE;
00944 }
00945 }
00946 }
00947
00948 if (status)
00949 {
00950 *status = statint;
00951 }
00952
00953 return file;
00954 }
00955
00956 int drms_segment_fclose(FILE *fptr)
00957 {
00958 int ret = 0;
00959
00960 if (fptr)
00961 {
00962 ret = fclose(fptr);
00963 if (ret)
00964 {
00965 ret = DRMS_ERROR_IOERROR;
00966 }
00967 }
00968
00969 return ret;
00970 }
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 DRMS_Array_t *drms_segment_read(DRMS_Segment_t *seg, DRMS_Type_t type,
00987 int *status)
00988 {
00989 int statint=0,i;
00990 DRMS_Array_t *arr = NULL;
00991 char filename[DRMS_MAXPATHLEN];
00992 DRMS_Record_t *rec;
00993
00994 CHECKNULL_STAT(seg,status);
00995
00996 rec = seg->record;
00997
00998 if (seg->info->scope == DRMS_CONSTANT &&
00999 !seg->info->cseg_recnum) {
01000 fprintf(stderr, "ERROR in drms_segment_read: constant segment has not yet"
01001 " been initialized. Series = %s.\n", rec->seriesinfo->seriesname);
01002 statint = DRMS_ERROR_INVALIDACTION;
01003 goto bailout1;
01004 }
01005
01006 if (seg->info->protocol == DRMS_GENERIC)
01007 {
01008 fprintf(stderr, "ERROR in drms_segment_read: Not appropriate function"
01009 "for DRMS_GENERIC segment. Series = %s.\n", rec->seriesinfo->seriesname);
01010 statint = DRMS_ERROR_INVALIDACTION;
01011 goto bailout1;
01012 }
01013
01014 if (rec->sunum != -1LL && rec->su==NULL)
01015 {
01016
01017 if ((rec->su = drms_getunit(rec->env, rec->seriesinfo->seriesname,
01018 rec->sunum, 1, &statint)) == NULL)
01019 {
01020
01021
01022
01023
01024
01025
01026 statint = DRMS_ERROR_NOSTORAGEUNIT;
01027 goto bailout1;
01028 }
01029 rec->su->refcount++;
01030 }
01031
01032 drms_segment_filename(seg, filename);
01033 #ifdef DEBUG
01034 printf("Trying to open segment file '%s'.\n",filename);
01035 #endif
01036
01037 if (seg->info->protocol == DRMS_DSDS || seg->info->protocol == DRMS_LOCAL)
01038 {
01039
01040
01041
01042 char *dsdsParams;
01043 int ds;
01044 int rn;
01045 char *locfilename;
01046
01047 if (seg->info->protocol == DRMS_DSDS)
01048 {
01049 if (!*filename)
01050 {
01051
01052
01053
01054
01055 fprintf(stderr, "There is no data file for this DSDS data record.\n");
01056 goto bailout1;
01057 }
01058
01059
01060
01061 dsdsParams = (char *)malloc(sizeof(char) * kDSDS_MaxHandle);
01062 if (DSDS_GetDSDSParams(seg->record->seriesinfo, dsdsParams))
01063 {
01064 fprintf(stderr, "Couldn't get DSDS keylist.\n");
01065 goto bailout1;
01066 }
01067
01068 ds = drms_getkey_int(seg->record, kDSDS_DS, &statint);
01069 rn = drms_getkey_int(seg->record, kDSDS_RN, &statint);
01070
01071 locfilename = NULL;
01072 }
01073 else
01074 {
01075 dsdsParams = NULL;
01076 ds = -1;
01077 rn = -1;
01078 locfilename = strdup(seg->filename);
01079 }
01080
01081
01082
01083 static void *hDSDS = NULL;
01084 static int attempted = 0;
01085
01086 if (!attempted && !hDSDS)
01087 {
01088 kDSDS_Stat_t dsdsstat;
01089 hDSDS = DSDS_GetLibHandle(kLIBDSDS, &dsdsstat);
01090 if (dsdsstat != kDSDS_Stat_Success)
01091 {
01092 statint = DRMS_ERROR_CANTOPENLIBRARY;
01093 }
01094
01095 attempted = 1;
01096 }
01097
01098 if (hDSDS)
01099 {
01100 kDSDS_Stat_t dsdsStat;
01101 pDSDSFn_DSDS_segment_read_t pFn_DSDS_segment_read =
01102 (pDSDSFn_DSDS_segment_read_t)DSDS_GetFPtr(hDSDS, kDSDS_DSDS_SEGMENT_READ);
01103 pDSDSFn_DSDS_free_array_t pFn_DSDS_free_array =
01104 (pDSDSFn_DSDS_free_array_t)DSDS_GetFPtr(hDSDS, kDSDS_DSDS_FREE_ARRAY);
01105
01106 if (pFn_DSDS_segment_read && pFn_DSDS_free_array)
01107 {
01108 DRMS_Array_t *copy = NULL;
01109
01110 if (statint == DRMS_SUCCESS)
01111 {
01112 arr = (*pFn_DSDS_segment_read)(dsdsParams, ds, rn, locfilename, &dsdsStat);
01113 }
01114 else
01115 {
01116 goto bailout1;
01117 }
01118
01119 if (dsdsStat == kDSDS_Stat_Success)
01120 {
01121
01122 long long datalen = drms_array_size(arr);
01123 void *data = calloc(1, datalen);
01124 if (data)
01125 {
01126 memcpy(data, arr->data, datalen);
01127 copy = drms_array_create(arr->type, arr->naxis, arr->axis, data, &statint);
01128 if (statint != DRMS_SUCCESS)
01129 {
01130 if (data)
01131 {
01132 free(data);
01133 }
01134 goto bailout;
01135 }
01136 }
01137 else
01138 {
01139 statint = DRMS_ERROR_OUTOFMEMORY;
01140 goto bailout;
01141 }
01142
01143 copy->bzero = arr->bzero;
01144 copy->bscale = arr->bscale;
01145 copy->israw = arr->israw;
01146
01147 (*pFn_DSDS_free_array)(&arr);
01148 arr = copy;
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 if (copy->type == DRMS_TYPE_INT || copy->type == DRMS_TYPE_LONGLONG)
01175 {
01176 drms_array_convert_inplace(DRMS_TYPE_DOUBLE, arr->bzero, arr->bscale, arr);
01177 }
01178 else if (copy->type == DRMS_TYPE_CHAR || copy->type == DRMS_TYPE_SHORT)
01179 {
01180 drms_array_convert_inplace(DRMS_TYPE_FLOAT, arr->bzero, arr->bscale, arr);
01181 }
01182 }
01183 else
01184 {
01185 statint = DRMS_ERROR_LIBDSDS;
01186 fprintf(stderr, "Error reading DSDS segment.\n");
01187 goto bailout1;
01188 }
01189 }
01190 else
01191 {
01192 statint = DRMS_ERROR_LIBDSDS;
01193 goto bailout1;
01194 }
01195 }
01196 else
01197 {
01198 fprintf(stdout, "Your JSOC environment does not support DSDS database access.\n");
01199 statint = DRMS_ERROR_NODSDSSUPPORT;
01200 }
01201
01202 if (dsdsParams)
01203 {
01204 free(dsdsParams);
01205 }
01206
01207 if (locfilename)
01208 {
01209 free(locfilename);
01210 }
01211
01212 }
01213 else
01214 {
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 struct stat stbuf;
01226
01227 if (stat(filename, &stbuf))
01228 {
01229
01230 statint = DRMS_ERROR_INVALIDFILE;
01231 goto bailout1;
01232 }
01233
01234 switch(seg->info->protocol)
01235 {
01236 case DRMS_GENERIC:
01237 case DRMS_MSI:
01238 statint = DRMS_ERROR_NOTIMPLEMENTED;
01239 goto bailout1;
01240 break;
01241 case DRMS_BINARY:
01242 arr = malloc(sizeof(DRMS_Array_t));
01243 XASSERT(arr);
01244 if ((statint = drms_binfile_read(filename, 0, arr)))
01245 {
01246 fprintf(stderr,"Couldn't read segment from file '%s'.\n",
01247 filename);
01248 goto bailout1;
01249 }
01250 break;
01251 case DRMS_BINZIP:
01252 arr = malloc(sizeof(DRMS_Array_t));
01253 XASSERT(arr);
01254 if ((statint = drms_zipfile_read(filename, 0, arr)))
01255 {
01256 fprintf(stderr,"Couldn't read segment from file '%s'.\n",
01257 filename);
01258 goto bailout1;
01259 }
01260 break;
01261 case DRMS_FITZ:
01262 case DRMS_FITS:
01263 {
01264 CFITSIO_IMAGE_INFO *info = NULL;
01265 void *image = NULL;
01266
01267
01268 if (fitsrw_readintfile(rec->env->verbose, filename, &info, &image, NULL) == CFITSIO_SUCCESS)
01269 {
01270 if (drms_fitsrw_CreateDRMSArray(info, image, &arr))
01271 {
01272 fprintf(stderr,"Couldn't read segment from file '%s'.\n", filename);
01273 goto bailout1;
01274 }
01275
01276
01277 cfitsio_free_these(&info, NULL, NULL);
01278 }
01279 else
01280 {
01281
01282 fprintf(stderr,"Couldn't read FITS file '%s'.\n", filename);
01283 statint = DRMS_ERROR_FITSRW;
01284 goto bailout1;
01285 }
01286 }
01287 break;
01288 case DRMS_FITZDEPRECATED:
01289 case DRMS_FITSDEPRECATED:
01290 {
01291 arr = NULL;
01292 statint = DRMS_ERROR_NOTIMPLEMENTED;
01293 fprintf(stderr,"Protocol DRMS_FITSDEPRECATED and DRMS_FITZDEPRECATED have been deprecated.\n");
01294 goto bailout1;
01295 }
01296 break;
01297 case DRMS_TAS:
01298 {
01299
01300
01301
01302
01303
01304
01305
01306 if ((statint = drms_fitstas_readslice(seg->record->env,
01307 filename,
01308 seg->info->naxis,
01309 seg->axis,
01310 NULL,
01311 NULL,
01312 seg->record->slotnum,
01313 &arr)) != DRMS_SUCCESS)
01314 {
01315 fprintf(stderr,"Couldn't read segment from file '%s'.\n",
01316 filename);
01317 goto bailout1;
01318 }
01319 }
01320 break;
01321 default:
01322 statint = DRMS_ERROR_UNKNOWNPROTOCOL;
01323 goto bailout1;
01324 }
01325 }
01326
01327
01328 if (arr->type != seg->info->type) {
01329 fprintf (stderr, "Data types in file (%d) do not match those in segment "
01330 "descriptor (%d).\n", (int)arr->type, (int)seg->info->type);
01331 statint = DRMS_ERROR_SEGMENT_DATA_MISMATCH;
01332 goto bailout;
01333 }
01334 if (arr->naxis != seg->info->naxis) {
01335 fprintf (stderr, "Number of axis in file (%d) do not match those in "
01336 "segment descriptor (%d).\n", arr->naxis, seg->info->naxis);
01337 statint = DRMS_ERROR_SEGMENT_DATA_MISMATCH;
01338 goto bailout;
01339 }
01340
01341 if (seg->info->scope != DRMS_VARDIM)
01342 {
01343 for (i=0;i<arr->naxis;i++) {
01344 if (arr->axis[i] != seg->axis[i]) {
01345 fprintf (stderr,"Dimension of axis %d in file (%d) do not match those"
01346 " in segment descriptor (%d).\n", i, arr->axis[i], seg->axis[i]);
01347 statint = DRMS_ERROR_SEGMENT_DATA_MISMATCH;
01348 goto bailout;
01349 }
01350 }
01351 }
01352
01353 for (i=0;i<arr->naxis;i++)
01354 arr->start[i] = 0;
01355
01356
01357 arr->parent_segment = seg;
01358
01359
01360 if (type == DRMS_TYPE_RAW)
01361 {
01362 arr->israw = 1;
01363 }
01364 else if (arr->type != type || arr->bscale != 1.0 || arr->bzero != 0.0)
01365 {
01366
01367 drms_array_convert_inplace(type, arr->bzero, arr->bscale, arr);
01368 #ifdef DEBUG
01369 printf("converted with bzero=%g, bscale=%g\n",arr->bzero, arr->bscale);
01370 #endif
01371 arr->israw = 0;
01372 }
01373
01374 if (status)
01375 *status = DRMS_SUCCESS;
01376
01377 return arr;
01378
01379 bailout:
01380 free(arr->data);
01381 free(arr);
01382 bailout1:
01383 #ifdef DEBUG
01384 printf("Segment = \n");
01385 drms_segment_print(seg);
01386 #endif
01387 if (status)
01388 *status = statint;
01389 return NULL;
01390 }
01391
01392
01393
01394
01395
01396 DRMS_Array_t *drms_segment_readslice(DRMS_Segment_t *seg, DRMS_Type_t type,
01397 axislen_t *start, axislen_t *end, int *status)
01398 {
01399 int statint = 0, i;
01400 DRMS_Array_t *arr, *tmp;
01401 char filename[DRMS_MAXPATHLEN];
01402 DRMS_Record_t *rec;
01403
01404 CHECKNULL_STAT(seg,status);
01405
01406 rec = seg->record;
01407 if (rec->sunum != -1LL && rec->su==NULL)
01408 {
01409
01410 if ((rec->su = drms_getunit(rec->env, rec->seriesinfo->seriesname,
01411 rec->sunum, 1, &statint)) == NULL)
01412 {
01413
01414
01415
01416
01417
01418
01419 statint = DRMS_ERROR_NOSTORAGEUNIT;
01420 goto bailout1;
01421 }
01422 rec->su->refcount++;
01423 }
01424
01425 drms_segment_filename(seg, filename);
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437 struct stat stbuf;
01438
01439 if (stat(filename, &stbuf))
01440 {
01441
01442 statint = DRMS_ERROR_INVALIDFILE;
01443 goto bailout1;
01444 }
01445
01446
01447
01448
01449
01450
01451 if (seg->info->protocol == DRMS_FITS ||
01452 seg->info->protocol == DRMS_FITZ)
01453 {
01454
01455
01456
01457
01458 if ((statint = drms_fitsrw_readslice(rec->env,
01459 filename,
01460 seg->info->naxis,
01461 start,
01462 end,
01463 &arr)) != DRMS_SUCCESS)
01464 {
01465 fprintf(stderr,"Couldn't read slice from file '%s'.\n", filename);
01466 goto bailout1;
01467 }
01468 }
01469 else if (seg->info->protocol == DRMS_TAS)
01470 {
01471 if ((statint = drms_fitstas_readslice(rec->env,
01472 filename,
01473 seg->info->naxis,
01474 seg->axis,
01475 start,
01476 end,
01477 seg->record->slotnum,
01478 &arr)) != DRMS_SUCCESS)
01479 {
01480 fprintf(stderr,"Couldn't read slice from file '%s'.\n", filename);
01481 goto bailout1;
01482 }
01483 }
01484 else
01485 {
01486 switch(seg->info->protocol)
01487 {
01488 case DRMS_BINARY:
01489 arr = malloc(sizeof(DRMS_Array_t));
01490 XASSERT(arr);
01491 if ((statint = drms_binfile_read(filename, 0, arr)))
01492 {
01493 fprintf(stderr,"Couldn't read segment from file '%s'.\n",
01494 filename);
01495 goto bailout1;
01496 }
01497 break;
01498 case DRMS_BINZIP:
01499 arr = malloc(sizeof(DRMS_Array_t));
01500 XASSERT(arr);
01501 if ((statint = drms_zipfile_read(filename, 0, arr)))
01502 {
01503 fprintf(stderr,"Couldn't read segment from file '%s'.\n",
01504 filename);
01505 goto bailout1;
01506 }
01507 break;
01508 case DRMS_GENERIC:
01509 *status = DRMS_ERROR_INVALIDACTION;
01510 return NULL;
01511 break;
01512 case DRMS_MSI:
01513 *status = DRMS_ERROR_NOTIMPLEMENTED;
01514 return NULL;
01515 break;
01516 case DRMS_FITZDEPRECATED:
01517 case DRMS_FITSDEPRECATED:
01518 {
01519 arr = NULL;
01520 statint = DRMS_ERROR_NOTIMPLEMENTED;
01521 fprintf(stderr,"Protocols DRMS_FITSDEPRECATED and DRMS_FITZDEPRECATED have been deprecated.\n");
01522 goto bailout1;
01523 }
01524 break;
01525 default:
01526 if (status)
01527 *status = DRMS_ERROR_UNKNOWNPROTOCOL;
01528 return NULL;
01529 }
01530
01531
01532 if ((tmp = drms_array_slice(start,end,arr)) == NULL)
01533 drms_free_array(arr);
01534 arr = tmp;
01535 if (!arr)
01536 goto bailout1;
01537 }
01538
01539
01540 if (arr->type != seg->info->type) {
01541 fprintf (stderr, "Data types in file (%d) do not match those in segment "
01542 "descriptor (%d).\n", (int)arr->type, (int)seg->info->type);
01543 statint = DRMS_ERROR_SEGMENT_DATA_MISMATCH;
01544 goto bailout;
01545 }
01546 if (arr->naxis != seg->info->naxis) {
01547 fprintf (stderr, "Number of axis in file (%d) do not match those in "
01548 "segment descriptor (%d).\n", arr->naxis, seg->info->naxis);
01549 statint = DRMS_ERROR_SEGMENT_DATA_MISMATCH;
01550 goto bailout;
01551 }
01552
01553 if (seg->info->scope != DRMS_VARDIM)
01554 {
01555 for (i=0;i<arr->naxis;i++) {
01556 if (arr->axis[i] > seg->axis[i]) {
01557 fprintf (stderr,"Dimension of axis %d in file (%d) is incompatible with those"
01558 " in segment descriptor (%d).\n", i, arr->axis[i], seg->axis[i]);
01559 statint = DRMS_ERROR_SEGMENT_DATA_MISMATCH;
01560 goto bailout;
01561 }
01562 }
01563 }
01564
01565 for (i=0;i<arr->naxis;i++)
01566 arr->start[i] = 0;
01567
01568
01569 arr->parent_segment = seg;
01570
01571
01572 if (type == DRMS_TYPE_RAW)
01573 {
01574 arr->israw = 1;
01575 }
01576 else if (arr->type != type || arr->bscale != 1.0 || arr->bzero != 0.0)
01577 {
01578
01579 drms_array_convert_inplace(type, arr->bzero, arr->bscale, arr);
01580 #ifdef DEBUG
01581 printf("converted with bzero=%g, bscale=%g\n",arr->bzero, arr->bscale);
01582 #endif
01583 arr->israw = 0;
01584 }
01585
01586 if (status)
01587 *status = DRMS_SUCCESS;
01588
01589 return arr;
01590
01591 bailout:
01592 drms_free_array(arr);
01593 bailout1:
01594 if (status)
01595 *status = statint;
01596 return NULL;
01597 }
01598
01599
01600 static DRMS_Array_t *ScaleOutputArray(DRMS_Segment_t *seg, DRMS_Array_t *arr, int autoscale)
01601 {
01602 double autobscale, autobzero;
01603 double bscale, bzero;
01604
01605
01606
01607 if (autoscale)
01608 drms_segment_autoscale(seg, arr, &autobzero, &autobscale);
01609
01610 int outisraw = 0;
01611 int copyarrscale = 0;
01612
01613 DRMS_Array_t *out = NULL;
01614
01615
01616
01617 if (arr->type != DRMS_TYPE_FLOAT && arr->type != DRMS_TYPE_DOUBLE)
01618 {
01619
01620
01621 if (arr->israw)
01622 {
01623
01624 if (seg->info->type == DRMS_TYPE_FLOAT || seg->info->type == DRMS_TYPE_DOUBLE)
01625 {
01626
01627 bzero = arr->bzero;
01628 bscale = arr->bscale;
01629
01630 copyarrscale = 0;
01631 outisraw = 0;
01632 }
01633 else
01634 {
01635
01636
01637 if (!autoscale)
01638 {
01639 bzero = 0.0;
01640 bscale = 1.0;
01641 }
01642 else
01643 {
01644 if (arr->bzero != autobzero || arr->bscale != autobscale)
01645 {
01646 bzero = (arr->bzero - autobzero) / autobscale;
01647 bscale = (arr->bscale) / autobscale;
01648 }
01649 else
01650 {
01651 bzero = 0.0;
01652 bscale = 1.0;
01653 }
01654 }
01655
01656 copyarrscale = 1;
01657 outisraw = 1;
01658 }
01659 }
01660 else
01661 {
01662
01663 if (!autoscale)
01664 {
01665 bzero = 0.0;
01666 bscale = 1.0;
01667 }
01668 else if (autobzero != 0.0 || autobscale != 1.0)
01669 {
01670 bzero = -autobzero / autobscale;
01671 bscale = 1.0 / autobscale;
01672 }
01673
01674 copyarrscale = 0;
01675 outisraw = 0;
01676 }
01677 }
01678 else
01679 {
01680
01681 if (seg->info->type != DRMS_TYPE_FLOAT && seg->info->type != DRMS_TYPE_DOUBLE)
01682 {
01683
01684 if (!autoscale)
01685 {
01686 bzero = -arr->bzero / arr->bscale;
01687 bscale = 1.0 / arr->bscale;
01688 }
01689 else
01690 {
01691 bzero = -autobzero / autobscale;
01692 bscale = 1.0 / autobscale;
01693 }
01694
01695 copyarrscale = 1;
01696 outisraw = 1;
01697 }
01698 else
01699 {
01700
01701 bzero = 0.0;
01702 bscale = 1.0;
01703 copyarrscale = 0;
01704 outisraw = 0;
01705 }
01706 }
01707
01708 #ifdef DEBUG
01709 printf("in write_segment: bzero=%g, bscale = %g\n",bzero,bscale);
01710 #endif
01711
01712
01713 if( arr->type != seg->info->type || fabs(bzero)!=0.0 || bscale!=1.0)
01714 {
01715 out = drms_array_convert(seg->info->type, bzero, bscale, arr);
01716 }
01717 else
01718 {
01719 out = arr;
01720 }
01721
01722 if (copyarrscale)
01723 {
01724 out->bzero = arr->bzero;
01725 out->bscale = arr->bscale;
01726 }
01727 else
01728 {
01729 out->bzero = 0.0;
01730 out->bscale = 1.0;
01731 }
01732 out->israw = outisraw ? 1 : 0;
01733
01734 return out;
01735 }
01736
01737
01738
01739
01740 static int drms_segment_writeinternal(DRMS_Segment_t *seg, DRMS_Array_t *arr, int autoscale, int wkeys)
01741 {
01742 int status,i;
01743 char filename[DRMS_MAXPATHLEN];
01744 DRMS_Array_t *out;
01745 DRMS_SeriesVersion_t vers2_1 = {"2.1", ""};
01746 CFITSIO_KEYWORD *fitskeys = NULL;
01747
01748 if (seg->info->scope == DRMS_CONSTANT &&
01749 seg->info->cseg_recnum) {
01750 fprintf(stderr, "ERROR in drms_segment_write: constant segment has already"
01751 " been initialized. Series = %s.\n", seg->record->seriesinfo->seriesname);
01752 return DRMS_ERROR_INVALIDACTION;
01753 }
01754
01755 if (seg->info->protocol == DRMS_GENERIC)
01756 {
01757 fprintf(stderr, "ERROR in drms_segment_write: Not appropriate function"
01758 "for DRMS_GENERIC segment. Series = %s.\n", seg->record->seriesinfo->seriesname);
01759 return(DRMS_ERROR_INVALIDACTION);
01760 }
01761
01762 if (seg && arr)
01763 {
01764 if (seg->record->readonly)
01765 {
01766 fprintf(stderr,"Cannot write segment to read-only record.\n");
01767 return DRMS_ERROR_RECORDREADONLY;
01768 }
01769 if (arr->data == NULL)
01770 {
01771 fprintf(stderr,"Array contains no data!\n");
01772 return DRMS_ERROR_NULLPOINTER;
01773 }
01774
01775 if (seg->info->scope != DRMS_VARDIM)
01776 {
01777 if (arr->naxis != seg->info->naxis)
01778 {
01779 fprintf(stderr,"Number of axis in file (%d) do not match those in "
01780 "segment descriptor (%d).\n",arr->naxis,seg->info->naxis);
01781 return DRMS_ERROR_INVALIDDIMS;
01782 }
01783 for (i=0;i<arr->naxis;i++)
01784 {
01785 if (arr->axis[i] != seg->axis[i])
01786 {
01787 fprintf(stderr,"Dimension of axis %d in file (%d) do not match those"
01788 " in segment descriptor (%d).\n",i,arr->axis[i],
01789 seg->axis[i]);
01790 return DRMS_ERROR_INVALIDDIMS;
01791 }
01792 }
01793 }
01794 else
01795 {
01796
01797 seg->info->naxis = arr->naxis;
01798
01799 for (i=0;i<arr->naxis;i++)
01800 {
01801 seg->axis[i] = arr->axis[i];
01802 }
01803 }
01804
01805 out = ScaleOutputArray(seg, arr, autoscale);
01806
01807 drms_segment_filename(seg, filename);
01808 if (!strlen(seg->filename)) {
01809 strncpy(seg->filename, rindex(filename, '/')+1, DRMS_MAXSEGFILENAME-1);
01810 }
01811
01812 char key[DRMS_MAXKEYNAMELEN];
01813
01814 switch(seg->info->protocol)
01815 {
01816 case DRMS_BINARY:
01817 status = drms_binfile_write(filename, out);
01818
01819 if (drms_series_isvers(seg->record->seriesinfo, &vers2_1))
01820 {
01821 if (!drms_segment_checkscaling(out, seg->bzero, seg->bscale))
01822 {
01823 snprintf(key, sizeof(key), "%s_bzero", seg->info->name);
01824 drms_setkey_double(seg->record, key, out->bzero);
01825 snprintf(key, sizeof(key), "%s_bscale", seg->info->name);
01826 drms_setkey_double(seg->record, key, out->bscale);
01827 }
01828 }
01829
01830 if (status)
01831 goto bailout;
01832 break;
01833 case DRMS_BINZIP:
01834 status = drms_zipfile_write(filename, out);
01835
01836 if (drms_series_isvers(seg->record->seriesinfo, &vers2_1))
01837 {
01838 if (!drms_segment_checkscaling(out, seg->bzero, seg->bscale))
01839 {
01840 snprintf(key, sizeof(key), "%s_bzero", seg->info->name);
01841 drms_setkey_double(seg->record, key, out->bzero);
01842 snprintf(key, sizeof(key), "%s_bscale", seg->info->name);
01843 drms_setkey_double(seg->record, key, out->bscale);
01844 }
01845 }
01846
01847 if (status)
01848 goto bailout;
01849 break;
01850 case DRMS_FITZ:
01851 {
01852 if (out->type == DRMS_TYPE_STRING)
01853 {
01854 fprintf(stderr, "Can't save string data into a fits file.\n");
01855 status = DRMS_ERROR_INVALIDTYPE;
01856 goto bailout;
01857 }
01858
01859
01860 if (wkeys)
01861 {
01862 fitskeys = fitsexport_mapkeys(seg, NULL, NULL, &status);
01863 if (status)
01864 {
01865 fprintf(stderr, "WARNING - failure to export one or more keywords.\n");
01866 status = DRMS_SUCCESS;
01867 }
01868 }
01869
01870 CFITSIO_IMAGE_INFO imginfo;
01871
01872 if (!drms_fitsrw_SetImageInfo(out, &imginfo))
01873 {
01874
01875
01876 if (fitsrw_writeintfile(seg->record->env->verbose, filename, &imginfo, out->data, seg->cparms, fitskeys) != CFITSIO_SUCCESS)
01877 {
01878 status = DRMS_ERROR_FITSRW;
01879 goto bailout;
01880 }
01881
01882
01883
01884
01885
01886 if (drms_series_isvers(seg->record->seriesinfo, &vers2_1))
01887 {
01888 if (!drms_segment_checkscaling(out, seg->bzero, seg->bscale))
01889 {
01890 snprintf(key, sizeof(key), "%s_bzero", seg->info->name);
01891 drms_setkey_double(seg->record, key, drms_fitsrw_GetBzeroFromInfo(&imginfo));
01892 snprintf(key, sizeof(key), "%s_bscale", seg->info->name);
01893 drms_setkey_double(seg->record, key, drms_fitsrw_GetBscaleFromInfo(&imginfo));
01894 }
01895 }
01896 }
01897 else
01898 {
01899 status = DRMS_ERROR_SEGMENTWRITE;
01900 goto bailout;
01901 }
01902
01903 if (fitskeys)
01904 {
01905 cfitsio_free_keys(&fitskeys);
01906 }
01907 }
01908 break;
01909 case DRMS_FITS:
01910 {
01911 if (out->type == DRMS_TYPE_STRING)
01912 {
01913 fprintf(stderr, "Can't save string data into a fits file.\n");
01914 status = DRMS_ERROR_INVALIDTYPE;
01915 goto bailout;
01916 }
01917
01918
01919 if (wkeys)
01920 {
01921 fitskeys = fitsexport_mapkeys(seg, NULL, NULL, &status);
01922 if (status)
01923 {
01924 fprintf(stderr, "WARNING - failure to export one or more keywords.\n");
01925 status = DRMS_SUCCESS;
01926 }
01927 }
01928
01929 CFITSIO_IMAGE_INFO imginfo;
01930
01931 if (!drms_fitsrw_SetImageInfo(out, &imginfo))
01932 {
01933 if (fitsrw_writeintfile(seg->record->env->verbose, filename, &imginfo, out->data, seg->cparms, fitskeys) != CFITSIO_SUCCESS)
01934 {
01935 status = DRMS_ERROR_FITSRW;
01936 goto bailout;
01937 }
01938
01939
01940
01941
01942
01943 if (drms_series_isvers(seg->record->seriesinfo, &vers2_1))
01944 {
01945 if (!drms_segment_checkscaling(out, seg->bzero, seg->bscale))
01946 {
01947 snprintf(key, sizeof(key), "%s_bzero", seg->info->name);
01948 drms_setkey_double(seg->record, key, drms_fitsrw_GetBzeroFromInfo(&imginfo));
01949 snprintf(key, sizeof(key), "%s_bscale", seg->info->name);
01950 drms_setkey_double(seg->record, key, drms_fitsrw_GetBscaleFromInfo(&imginfo));
01951 }
01952 }
01953 }
01954 else
01955 {
01956 status = DRMS_ERROR_SEGMENTWRITE;
01957 goto bailout;
01958 }
01959
01960 if (fitskeys)
01961 {
01962 cfitsio_free_keys(&fitskeys);
01963 }
01964 }
01965 break;
01966 case DRMS_MSI:
01967 return DRMS_ERROR_NOTIMPLEMENTED;
01968 break;
01969 case DRMS_TAS:
01970 {
01971 char virgin[PATH_MAX];
01972 struct stat stBuf;
01973
01974
01975
01976
01977 if (drms_series_isvers(seg->record->seriesinfo, &vers2_1))
01978 {
01979 if (!drms_segment_checkscaling(out, seg->bzero, seg->bscale))
01980 {
01981 fprintf(stderr, "The output array's bzero/bscale values (%f, %f) do not match those of the TAS file (%f, %f).\n", out->bzero, out->bscale, seg->bzero, seg->bscale);
01982 status = DRMS_ERROR_INVALIDSCALING;
01983 goto bailout;
01984 }
01985 }
01986
01987 status = drms_fitstas_writeslice(seg->record->env,
01988 seg,
01989 filename,
01990 seg->info->naxis,
01991 seg->axis,
01992 NULL,
01993 NULL,
01994 seg->record->slotnum,
01995 out);
01996
01997 if (status)
01998 goto bailout;
01999
02000
02001
02002 snprintf(virgin, sizeof(virgin), "%s.virgin", filename);
02003 if (!stat(virgin, &stBuf))
02004 {
02005
02006 unlink(virgin);
02007 }
02008 }
02009 break;
02010 case DRMS_FITZDEPRECATED:
02011 status = DRMS_ERROR_NOTIMPLEMENTED;
02012 fprintf(stderr,"Protocol DRMS_FITZDEPRECATED has been deprecated.\n");
02013 goto bailout;
02014 break;
02015 case DRMS_FITSDEPRECATED:
02016 status = DRMS_ERROR_NOTIMPLEMENTED;
02017 fprintf(stderr,"Protocol DRMS_FITSDEPRECATED has been deprecated.\n");
02018 goto bailout;
02019 break;
02020 default:
02021 return DRMS_ERROR_UNKNOWNPROTOCOL;
02022 }
02023
02024 if (out!=arr)
02025 drms_free_array(out);
02026
02027 if (seg->info->scope == DRMS_CONSTANT &&
02028 !seg->info->cseg_recnum) {
02029 if (seg->record->lifetime == DRMS_TRANSIENT) {
02030 fprintf(stderr, "Error: cannot set constant segment in a transient record\n");
02031 status = DRMS_ERROR_SEGMENTWRITE;
02032 goto bailout;
02033 }
02034 return drms_segment_set_const(seg);
02035 }
02036
02037 return DRMS_SUCCESS;
02038 }
02039 else
02040 return DRMS_ERROR_NULLPOINTER;
02041
02042 bailout:
02043 if (out && out!=arr)
02044 drms_free_array(out);
02045
02046 if (fitskeys)
02047 {
02048 cfitsio_free_keys(&fitskeys);
02049 }
02050
02051 fprintf(stderr,"ERROR: Couldn't write data to file '%s'.\n", filename);
02052 return status;
02053 }
02054
02055 int drms_segment_write(DRMS_Segment_t *seg, DRMS_Array_t *arr, int autoscale)
02056 {
02057 return drms_segment_writeinternal(seg, arr, autoscale, 0);
02058 }
02059
02060 int drms_segment_writewithkeys(DRMS_Segment_t *seg, DRMS_Array_t *arr, int autoscale)
02061 {
02062 return drms_segment_writeinternal(seg, arr, autoscale, 1);
02063 }
02064
02065 int drms_segment_writeslice_ext(DRMS_Segment_t *seg,
02066 DRMS_Array_t *arr,
02067 axislen_t *start,
02068 axislen_t *end,
02069 int *finaldims,
02070 int autoscale)
02071 {
02072 int status,i;
02073 char filename[DRMS_MAXPATHLEN];
02074 DRMS_Array_t *out;
02075 DRMS_SeriesVersion_t vers2_1 = {"2.1", ""};
02076
02077 if (seg->info->scope == DRMS_CONSTANT &&
02078 seg->info->cseg_recnum) {
02079 fprintf(stderr, "ERROR in drms_segment_write: constant segment has already"
02080 " been initialized. Series = %s.\n", seg->record->seriesinfo->seriesname);
02081 return DRMS_ERROR_INVALIDACTION;
02082 }
02083
02084 if (seg->info->protocol == DRMS_GENERIC)
02085 {
02086 fprintf(stderr, "ERROR in drms_segment_write: Not appropriate function"
02087 "for DRMS_GENERIC segment. Series = %s.\n", seg->record->seriesinfo->seriesname);
02088 return(DRMS_ERROR_INVALIDACTION);
02089 }
02090
02091 if (seg && arr)
02092 {
02093 if (seg->record->readonly)
02094 {
02095 fprintf(stderr,"Cannot write segment to read-only record.\n");
02096 return DRMS_ERROR_RECORDREADONLY;
02097 }
02098 if (arr->data == NULL)
02099 {
02100 fprintf(stderr,"Array contains no data!\n");
02101 return DRMS_ERROR_NULLPOINTER;
02102 }
02103
02104 if (seg->info->scope != DRMS_VARDIM)
02105 {
02106 if (arr->naxis != seg->info->naxis)
02107 {
02108 fprintf(stderr,"Number of axis in file (%d) do not match those in "
02109 "segment descriptor (%d).\n",arr->naxis,seg->info->naxis);
02110 return DRMS_ERROR_INVALIDDIMS;
02111 }
02112 for (i=0;i<arr->naxis;i++)
02113 {
02114 if (start[i] < 0 || end[i] > seg->axis[i] - 1)
02115 {
02116 fprintf(stderr,
02117 "Axis slice '[%d, %d]' not entirely within data array boundaries.\n",
02118 start[i], end[i]);
02119 return DRMS_ERROR_INVALIDDIMS;
02120 }
02121
02122 if (end[i] - start[i] + 1 != arr->axis[i])
02123 {
02124 fprintf(stderr,
02125 "Axis slice dimensions (%d) do not match data dimensions (%d).\n",
02126 end[i] - start[i] + 1, arr->axis[i]);
02127 return DRMS_ERROR_INVALIDDIMS;
02128 }
02129 }
02130 }
02131 else
02132 {
02133 const char *riceID = "compress rice";
02134 size_t sizestr = 64;
02135 char *tilestr = malloc(sizestr);
02136 char strbuf[64];
02137
02138 memset(tilestr, 0, sizestr);
02139
02140 for (i=0;i<arr->naxis;i++)
02141 {
02142 if (i == 0)
02143 {
02144 snprintf(strbuf, sizeof(strbuf), "%d", arr->axis[i]);
02145 tilestr = base_strcatalloc(tilestr, strbuf, &sizestr);
02146 }
02147 else
02148 {
02149 snprintf(strbuf, sizeof(strbuf), ",%d", arr->axis[i]);
02150 tilestr = base_strcatalloc(tilestr, strbuf, &sizestr);
02151 }
02152 }
02153
02154
02155
02156 if (strcasestr(seg->cparms, "compress"))
02157 {
02158 snprintf(seg->cparms, sizeof(seg->cparms), "%s %s", riceID, tilestr);
02159 }
02160
02161 free(tilestr);
02162 }
02163
02164 out = ScaleOutputArray(seg, arr, autoscale);
02165
02166 drms_segment_filename(seg, filename);
02167 if (!strlen(seg->filename)) {
02168 strncpy(seg->filename, rindex(filename, '/')+1, DRMS_MAXSEGFILENAME-1);
02169 }
02170
02171 switch(seg->info->protocol)
02172 {
02173 case DRMS_GENERIC:
02174 case DRMS_BINARY:
02175 case DRMS_BINZIP:
02176 case DRMS_MSI:
02177 case DRMS_FITZDEPRECATED:
02178 case DRMS_FITSDEPRECATED:
02179 status = DRMS_ERROR_NOTIMPLEMENTED;
02180 fprintf(stderr,"Protocol DRMS_FITSDEPRECATED and DRMS_FITZDEPRECATED have been deprecated.\n");
02181 goto bailout;
02182 break;
02183 case DRMS_FITZ:
02184 case DRMS_FITS:
02185 {
02186 if (out->type == DRMS_TYPE_STRING)
02187 {
02188 fprintf(stderr, "Can't save string data into a fits file.\n");
02189 goto bailout;
02190 }
02191
02192
02193
02194
02195 if (drms_series_isvers(seg->record->seriesinfo, &vers2_1))
02196 {
02197 if (!drms_segment_checkscaling(out, seg->bzero, seg->bscale))
02198 {
02199 fprintf(stderr, "The output array's bzero/bscale values (%f, %f) do not match those of the FITS file (%f, %f).\n", out->bzero, out->bscale, seg->bzero, seg->bscale);
02200 status = DRMS_ERROR_INVALIDSCALING;
02201 goto bailout;
02202 }
02203 }
02204
02205 if ((status = drms_fitsrw_writeslice_ext(seg->record->env,
02206 seg,
02207 filename,
02208 out->naxis,
02209 start,
02210 end,
02211 finaldims,
02212 out)) != DRMS_SUCCESS)
02213 goto bailout;
02214 }
02215 break;
02216 case DRMS_TAS:
02217 {
02218 char virgin[PATH_MAX];
02219 struct stat stBuf;
02220
02221
02222
02223
02224 if (drms_series_isvers(seg->record->seriesinfo, &vers2_1))
02225 {
02226 if (!drms_segment_checkscaling(out, seg->bzero, seg->bscale))
02227 {
02228 fprintf(stderr, "The output array's bzero/bscale values (%f, %f) do not match those of the TAS file (%f, %f).\n", out->bzero, out->bscale, seg->bzero, seg->bscale);
02229 status = DRMS_ERROR_INVALIDSCALING;
02230 goto bailout;
02231 }
02232 }
02233
02234 if ((status = drms_fitstas_writeslice(seg->record->env,
02235 seg,
02236 filename,
02237 seg->info->naxis,
02238 seg->axis,
02239 start,
02240 end,
02241 seg->record->slotnum,
02242 out)) != DRMS_SUCCESS)
02243 goto bailout;
02244
02245
02246
02247 snprintf(virgin, sizeof(virgin), "%s.virgin", filename);
02248 if (!stat(virgin, &stBuf))
02249 {
02250
02251 unlink(virgin);
02252 }
02253 }
02254 break;
02255 default:
02256 return DRMS_ERROR_UNKNOWNPROTOCOL;
02257 }
02258
02259 if (out!=arr)
02260 drms_free_array(out);
02261
02262 if (seg->info->scope == DRMS_CONSTANT &&
02263 !seg->info->cseg_recnum) {
02264 if (seg->record->lifetime == DRMS_TRANSIENT) {
02265 fprintf(stderr, "Error: cannot set constant segment in a transient record\n");
02266 goto bailout;
02267 }
02268 return drms_segment_set_const(seg);
02269 }
02270
02271 return DRMS_SUCCESS;
02272 }
02273 else
02274 return DRMS_ERROR_NULLPOINTER;
02275
02276 bailout:
02277 if (out && out!=arr)
02278 drms_free_array(out);
02279 fprintf(stderr,"ERROR: Couldn't write data to file '%s'.\n", filename);
02280 return status;
02281 }
02282
02283 int drms_segment_writeslice(DRMS_Segment_t *seg,
02284 DRMS_Array_t *arr,
02285 axislen_t *start,
02286 axislen_t *end,
02287 int autoscale)
02288 {
02289 return drms_segment_writeslice_ext(seg, arr, start, end, NULL, autoscale);
02290 }
02291
02292 int drms_segment_write_from_file(DRMS_Segment_t *seg, const char *infile) {
02293 char *filename;
02294 char outfile[DRMS_MAXPATHLEN];
02295 FILE *in, *out;
02296 size_t read_size;
02297 const unsigned int bufsize = 16*1024;
02298 char *buf = malloc(bufsize*sizeof(char));
02299
02300 if (seg->info->scope == DRMS_CONSTANT &&
02301 seg->info->cseg_recnum) {
02302 fprintf(stderr, "ERROR in drms_segment_write: constant segment has already"
02303 " been initialized. Series = %s.\n", seg->record->seriesinfo->seriesname);
02304 return DRMS_ERROR_INVALIDACTION;
02305 }
02306
02307 if (seg->record->readonly) {
02308 fprintf(stderr, "ERROR in drms_segment_write_from_file: Can't use "
02309 "on readonly segment\n");
02310 return DRMS_ERROR_RECORDREADONLY;
02311 }
02312
02313
02314 if (seg->info->protocol != DRMS_GENERIC) {
02315 fprintf(stderr, "ERROR in drms_segment_write_from_file: Can't use "
02316 "on non-DRMS_GENERIC segment. Series = %s.\n", seg->record->seriesinfo->seriesname);
02317 return DRMS_ERROR_INVALIDACTION;
02318 }
02319
02320 if ((in = fopen(infile, "r")) == NULL) {
02321 fprintf(stderr, "Error:Unable to open %s\n", infile);
02322 goto bailout;
02323 }
02324
02325 filename = rindex(infile, '/');
02326 if (filename)
02327 filename++;
02328 else
02329 filename = infile;
02330
02331 CHECKSNPRINTF(snprintf(seg->filename, DRMS_MAXSEGFILENAME, "%s", filename), DRMS_MAXSEGFILENAME);
02332 drms_segment_filename(seg, outfile);
02333 if ((out = fopen(outfile, "w")) == NULL) {
02334 fprintf(stderr, "Error:Unable to open %s\n", outfile);
02335 goto bailout;
02336 }
02337 while (1) {
02338 read_size = fread(buf, 1, bufsize, in);
02339 if (ferror(in)) {
02340 fprintf(stderr, "Error:Read error\n");
02341 goto bailout1;
02342 }
02343 else if (read_size == 0) {
02344 break;
02345 }
02346
02347 fwrite(buf, 1, read_size, out);
02348 }
02349 fclose(in);
02350 fclose(out);
02351 free(buf);
02352 buf = NULL;
02353
02354 if (seg->info->scope == DRMS_CONSTANT &&
02355 !seg->info->cseg_recnum) {
02356
02357 if (seg->record->lifetime == DRMS_TRANSIENT) {
02358 fprintf(stderr, "Error: cannot set constant segment in a transient record\n");
02359 goto bailout;
02360 }
02361 return drms_segment_set_const(seg);
02362 }
02363
02364 return DRMS_SUCCESS;
02365
02366 bailout1:
02367 unlink(outfile);
02368 bailout:
02369 if (buf)
02370 free(buf);
02371 seg->filename[0] = '\0';
02372 return 1;
02373 }
02374
02375 void drms_segment_setblocksize(DRMS_Segment_t *seg, int *blksz)
02376 {
02377 memcpy(seg->blocksize,blksz,seg->info->naxis*sizeof(int));
02378 }
02379
02380
02381 void drms_segment_getblocksize(DRMS_Segment_t *seg, int *blksz)
02382 {
02383 memcpy(blksz,seg->blocksize,seg->info->naxis*sizeof(int));
02384 }
02385
02386
02387
02388
02389
02390
02391 void drms_segment_autoscale(DRMS_Segment_t *seg,
02392 DRMS_Array_t *arr,
02393 double *autobzero,
02394 double *autobscale)
02395 {
02396 int iscale;
02397 arraylen_t i;
02398 arraylen_t n;
02399 double outmin, outmax;
02400 double inmin, inmax;
02401 double val, bscale, bzero;
02402
02403 switch(seg->info->type)
02404 {
02405 case DRMS_TYPE_CHAR:
02406 outmin = (double)SCHAR_MIN+1;
02407 outmax = (double)SCHAR_MAX;
02408 break;
02409 case DRMS_TYPE_SHORT:
02410 outmin = (double)SHRT_MIN+1;
02411 outmax = (double)SHRT_MAX;
02412 break;
02413 case DRMS_TYPE_INT:
02414 outmin = (double)INT_MIN+1;
02415 outmax = (double)INT_MAX;
02416 break;
02417 case DRMS_TYPE_LONGLONG:
02418 outmin = (double)LLONG_MIN+1;
02419 outmax = (double)LLONG_MAX;
02420 break;
02421 case DRMS_TYPE_FLOAT:
02422 case DRMS_TYPE_DOUBLE:
02423 case DRMS_TYPE_TIME:
02424 case DRMS_TYPE_STRING:
02425 return;
02426 default:
02427 fprintf(stderr, "ERROR: Unhandled DRMS type %d\n",(int)seg->info->type);
02428 XASSERT(0);
02429 }
02430
02431 n = drms_array_count(arr);
02432
02433 iscale = (trunc(arr->bscale)==arr->bscale && trunc(arr->bzero)==arr->bzero);
02434 bzero=0.0;
02435 bscale=1.0;
02436 switch(arr->type)
02437 {
02438 case DRMS_TYPE_CHAR:
02439 if (arr->israw || CHAR_MAX>outmax || CHAR_MIN<outmin)
02440 {
02441 char *p = (char *)arr->data;
02442 inmin = (double) *p;
02443 inmax = (double) *p++;
02444 for (i=1; i<n; i++)
02445 {
02446 val = (double) *p++;
02447 if (val<inmin)
02448 inmin = val;
02449 if (val>inmax)
02450 inmax = val;
02451 }
02452 if (arr->israw)
02453 {
02454 inmax = arr->bscale*inmax + arr->bzero;
02455 inmin = arr->bscale*inmin + arr->bzero;
02456
02457
02458 if ( iscale && inmax<=outmax && inmin>=outmin)
02459 {
02460 bzero = arr->bzero;
02461 bscale = arr->bscale;
02462 }
02463 else
02464 {
02465 bzero = (inmax+inmin)/2;
02466 bscale = (inmax-inmin)/(outmax-outmin);
02467 }
02468 }
02469 else
02470 {
02471 if (inmax<=outmax && inmin>=outmin)
02472 {
02473 bzero = 0.0;
02474 bscale = 1.0;
02475 }
02476 else
02477 {
02478 bzero = (inmax+inmin)/2;
02479 bscale = (inmax-inmin)/(outmax-outmin);
02480 }
02481 }
02482 }
02483
02484 *autobzero = bzero;
02485 *autobscale = bscale;
02486 break;
02487 case DRMS_TYPE_SHORT:
02488 if (arr->israw || SHRT_MAX>outmax || SHRT_MIN<outmin)
02489 {
02490 short *p = (short *)arr->data;
02491 inmin = (double) *p;
02492 inmax = (double) *p++;
02493 for (i=1; i<n; i++)
02494 {
02495 val = (double) *p++;
02496 if (val<inmin)
02497 inmin = val;
02498 if (val>inmax)
02499 inmax = val;
02500 }
02501 if (arr->israw)
02502 {
02503 inmax = arr->bscale*inmax + arr->bzero;
02504 inmin = arr->bscale*inmin + arr->bzero;
02505
02506
02507 if ( iscale && inmax<=outmax && inmin>=outmin)
02508 {
02509 bzero = arr->bzero;
02510 bscale = arr->bscale;
02511 }
02512 else
02513 {
02514 bzero = (inmax+inmin)/2;
02515 bscale = (inmax-inmin)/(outmax-outmin);
02516 }
02517 }
02518 else
02519 {
02520 if (inmax<=outmax && inmin>=outmin)
02521 {
02522 bzero = 0.0;
02523 bscale = 1.0;
02524 }
02525 else
02526 {
02527 bzero = (inmax+inmin)/2;
02528 bscale = (inmax-inmin)/(outmax-outmin);
02529 }
02530 }
02531 }
02532
02533 *autobzero = bzero;
02534 *autobscale = bscale;
02535 break;
02536 case DRMS_TYPE_INT:
02537 if (arr->israw || INT_MAX>outmax || INT_MIN<outmin)
02538 {
02539 int *p = (int *)arr->data;
02540 inmin = (double) *p;
02541 inmax = (double) *p++;
02542 for (i=1; i<n; i++)
02543 {
02544 val = (double) *p++;
02545 if (val<inmin)
02546 inmin = val;
02547 if (val>inmax)
02548 inmax = val;
02549 }
02550 if (arr->israw)
02551 {
02552 inmax = arr->bscale*inmax + arr->bzero;
02553 inmin = arr->bscale*inmin + arr->bzero;
02554
02555
02556 if ( iscale && inmax<=outmax && inmin>=outmin)
02557 {
02558 bzero = arr->bzero;
02559 bscale = arr->bscale;
02560 }
02561 else
02562 {
02563 bzero = (inmax+inmin)/2;
02564 bscale = (inmax-inmin)/(outmax-outmin);
02565 }
02566 }
02567 else
02568 {
02569 if (inmax<=outmax && inmin>=outmin)
02570 {
02571 bzero = 0.0;
02572 bscale = 1.0;
02573 }
02574 else
02575 {
02576 bzero = (inmax+inmin)/2;
02577 bscale = (inmax-inmin)/(outmax-outmin);
02578 }
02579 }
02580 }
02581
02582 *autobzero = bzero;
02583 *autobscale = bscale;
02584 break;
02585 case DRMS_TYPE_LONGLONG:
02586 if (arr->israw || LLONG_MAX>outmax || LLONG_MIN<outmin)
02587 {
02588 long long *p = (long long *)arr->data;
02589 inmin = (double) *p;
02590 inmax = (double) *p++;
02591 for (i=1; i<n; i++)
02592 {
02593 val = (double) *p++;
02594 if (val<inmin)
02595 inmin = val;
02596 if (val>inmax)
02597 inmax = val;
02598 }
02599 if (arr->israw)
02600 {
02601 inmax = arr->bscale*inmax + arr->bzero;
02602 inmin = arr->bscale*inmin + arr->bzero;
02603
02604
02605 if ( iscale && inmax<=outmax && inmin>=outmin)
02606 {
02607 bzero = arr->bzero;
02608 bscale = arr->bscale;
02609 }
02610 else
02611 {
02612 bzero = (inmax+inmin)/2;
02613 bscale = (inmax-inmin)/(outmax-outmin);
02614 }
02615 }
02616 else
02617 {
02618 if (inmax<=outmax && inmin>=outmin)
02619 {
02620 bzero = 0.0;
02621 bscale = 1.0;
02622 }
02623 else
02624 {
02625 bzero = (inmax+inmin)/2;
02626 bscale = (inmax-inmin)/(outmax-outmin);
02627 }
02628 }
02629 }
02630
02631 *autobzero = bzero;
02632 *autobscale = bscale;
02633 break;
02634 case DRMS_TYPE_FLOAT:
02635 if (!arr->israw && (seg->info->type==DRMS_TYPE_DOUBLE || seg->info->type==DRMS_TYPE_FLOAT))
02636 {
02637 *autobzero = 0.0;
02638 *autobscale = 1.0;
02639 }
02640 else
02641 {
02642 float *p = (float *)arr->data;
02643 inmin = (double) *p;
02644 inmax = (double) *p++;
02645 for (i=1; i<n; i++)
02646 {
02647 val = (double) *p++;
02648 if (val<inmin)
02649 inmin = val;
02650 if (val>inmax)
02651 inmax = val;
02652 }
02653 if (arr->israw)
02654 {
02655 inmax = arr->bscale*inmax + arr->bzero;
02656 inmin = arr->bscale*inmin + arr->bzero;
02657 }
02658 bzero = (inmax+inmin)/2;
02659 bscale = (inmax-inmin)/(outmax-outmin);
02660
02661 *autobzero = bzero;
02662 *autobscale = bscale;
02663 }
02664 break;
02665 case DRMS_TYPE_DOUBLE:
02666 case DRMS_TYPE_TIME:
02667 if (!arr->israw && (seg->info->type==DRMS_TYPE_DOUBLE))
02668 {
02669 *autobzero = 0.0;
02670 *autobscale = 1.0;
02671 }
02672 else
02673 {
02674 double *p = (double *)arr->data;
02675 inmin = (double) *p;
02676 inmax = (double) *p++;
02677 for (i=1; i<n; i++)
02678 {
02679 val = (double) *p++;
02680 if (val<inmin)
02681 inmin = val;
02682 if (val>inmax)
02683 inmax = val;
02684 }
02685 if (arr->israw)
02686 {
02687 inmax = arr->bscale*inmax + arr->bzero;
02688 inmin = arr->bscale*inmin + arr->bzero;
02689 }
02690 bzero = (inmax+inmin)/2;
02691 bscale = (inmax-inmin)/(outmax-outmin);
02692
02693 *autobzero = bzero;
02694 *autobscale = bscale;
02695 }
02696 break;
02697 case DRMS_TYPE_STRING:
02698 *autobzero = 0.0;
02699 *autobscale = 1.0;
02700 return;
02701 default:
02702 fprintf(stderr, "ERROR: Unhandled DRMS type %d\n",(int)arr->type);
02703 XASSERT(0);
02704 }
02705 }
02706
02707 int drms_segment_segsmatch(const DRMS_Segment_t *s1, const DRMS_Segment_t *s2)
02708 {
02709 int ret = 1;
02710
02711 if (s1 && s2)
02712 {
02713 int nDims = s1->info->naxis;
02714 if (nDims == s2->info->naxis)
02715 {
02716 int i = 0;
02717 for (; i < nDims; i++)
02718 {
02719 if (s1->axis[i] != s2->axis[i])
02720 {
02721 ret = 0;
02722 break;
02723 }
02724 }
02725
02726 if (s1->info->protocol == DRMS_TAS && s2->info->protocol == DRMS_TAS)
02727 {
02728 for (i = 0; ret == 1 && i < nDims; i++)
02729 {
02730 if (s1->blocksize[i] != s2->blocksize[i])
02731 {
02732 ret = 0;
02733 break;
02734 }
02735 }
02736 }
02737 }
02738 else
02739 {
02740 ret = 0;
02741 }
02742
02743 if (ret == 1)
02744 {
02745 if ((s1->info->type != s2->info->type) ||
02746 (s1->info->protocol != s2->info->protocol) ||
02747 (s2->info->scope != s2->info->scope))
02748 {
02749 ret = 0;
02750 }
02751 }
02752 }
02753 else if (s1 || s2)
02754 {
02755 ret = 0;
02756 }
02757
02758 return ret;
02759 }
02760
02761 static DRMS_Segment_t *TemplateSegFollowLink(DRMS_Segment_t *srcseg, int depth, int *statret)
02762 {
02763 int status = DRMS_SUCCESS;
02764 DRMS_Link_t *link = NULL;
02765 DRMS_Record_t *linktempl = NULL;
02766 DRMS_Segment_t *tgtseg = NULL;
02767
02768
02769 link = (DRMS_Link_t *)hcon_lookup_lower(&srcseg->record->links, srcseg->info->linkname);
02770 if (link)
02771 {
02772 linktempl = drms_template_record(srcseg->record->env, link->info->target_series, &status);
02773
02774 if (linktempl)
02775 {
02776 tgtseg = (DRMS_Segment_t *)hcon_lookup_lower(&linktempl->segments, srcseg->info->target_seg);
02777
02778 if (tgtseg)
02779 {
02780 if (tgtseg->info->islink)
02781 {
02782 if (depth < DRMS_MAXLINKDEPTH)
02783 {
02784 tgtseg = TemplateSegFollowLink(tgtseg, depth + 1, statret);
02785 }
02786 else
02787 {
02788 fprintf(stderr,
02789 "WARNING: Max link depth exceeded for segment '%s' in series '%s'.\n",
02790 srcseg->info->name,
02791 link->info->target_series);
02792 }
02793 }
02794 }
02795 else
02796 {
02797 if (statret)
02798 {
02799 *statret = DRMS_ERROR_UNKNOWNSEGMENT;
02800 }
02801 }
02802 }
02803 else
02804 {
02805 if (statret)
02806 {
02807 *statret = DRMS_ERROR_UNKNOWNSERIES;
02808 }
02809 }
02810 }
02811 else
02812 {
02813 if (statret)
02814 {
02815 *statret = DRMS_ERROR_UNKNOWNLINK;
02816 }
02817 }
02818
02819 return tgtseg;
02820 }
02821
02822 DRMS_Segment_t *drms_template_segment_followlink(DRMS_Segment_t *srcseg, int *statret)
02823 {
02824 return TemplateSegFollowLink(srcseg, 0, statret);
02825 }