00001
00002
00003
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <string.h>
00007 #include <limits.h>
00008 #include <dlfcn.h>
00009 #ifdef GCCCOMP
00010 #define __USE_GNU
00011 #endif
00012 #include <search.h>
00013 #include "drms_dsdsapi.h"
00014 #include "drms_types.h"
00015 #include "drms_protocol.h"
00016 #include "hcontainer.h"
00017 #include "list.h"
00018
00019
00020 #include "soi.h"
00021
00022 void *gHandleSOI = NULL;
00023 long long gSeriesGuid = 1;
00024 static HContainer_t *gHandleVDSCache = NULL;
00025
00026 const char kDSDS_GenericSeriesName[] = "dsds_series";
00027 #define kLIBSOI "libsoi.so"
00028 #define kDATAFILE "DATAFILE"
00029
00030
00031 typedef enum Soifn_enum
00032 {
00033 kSOI_VDS_OPEN = 0,
00034 kSOI_VDS_CLOSE,
00035 kSOI_VDS_SELECT_HDR,
00036 kSOI_VDS_SELECT_REC,
00037 kSOI_VDS_LAST_RECORD,
00038 kSOI_NEWKEYLIST,
00039 kSOI_FREEKEYLIST,
00040 kSOI_SETKEY_STR,
00041 kSOI_SETKEY_INT,
00042 kSOI_GETKEY_STR,
00043 kSOI_GETKEY_INT,
00044 kSOI_PARSE_LIST,
00045 kSOI_KEYITERATE,
00046 kSOI_SDS_DATA,
00047 kSOI_SDS_FREE_DATA,
00048 kSOI_SDS_DATATYPE,
00049 kSOI_SDS_DATA_LENGTH,
00050 kSOI_SDS_NUMBYTES,
00051 kSOI_SDS_RANK,
00052 kSOI_SDS_LENGTH,
00053 kSOI_SDS_FIRST_ATTR,
00054 kSOI_SDS_NEXT_ATTR,
00055 kSOI_SDS_LAST_ATTR,
00056 kSOI_SDS_ATTRNAME,
00057 kSOI_SDS_ATTRTYPE,
00058 kSOI_SDS_ATTRVALUE,
00059 kSOI_SDS_ATTRCOMMENT,
00060 kSOI_SDS_GET_FITS_HEAD,
00061 kSOI_SDS_FREE,
00062 kSOI_SDS_READ_FITS,
00063 kSOI_NFNS
00064 } Soifn_t;
00065
00066 char *SoifnNames[] =
00067 {
00068 "vds_open",
00069 "vds_close",
00070 "VDS_select_hdr",
00071 "VDS_select_rec",
00072 "vds_last_record",
00073 "newkeylist",
00074 "freekeylist",
00075 "setkey_str",
00076 "setkey_int",
00077 "getkey_str",
00078 "getkey_int",
00079 "parse_list",
00080 "keyiterate",
00081 "sds_data",
00082 "sds_free_data",
00083 "sds_datatype",
00084 "sds_data_length",
00085 "sds_numbytes",
00086 "sds_rank",
00087 "sds_length",
00088 "sds_first_attr",
00089 "sds_next_attr",
00090 "sds_last_attr",
00091 "sds_attrname",
00092 "sds_attrtype",
00093 "sds_attrvalue",
00094 "sds_attrcomment",
00095 "sds_get_fits_head",
00096 "sds_free",
00097 "sds_read_fits",
00098 ""
00099 };
00100
00101
00102 typedef VDS *(*pSOIFn_vds_open_t)(KEY *, char *);
00103 typedef int (*pSOIFn_vds_close_t)(VDS **);
00104 typedef SDS *(*pSOIFn_VDS_select_hdr_t)(VDS *, int, int);
00105 typedef SDS *(*pSOIFn_VDS_select_rec_t)(VDS *, int, int);
00106 typedef int (*pSOIFn_vds_last_record_t)(VDS *);
00107 typedef KEY *(*pSOIFn_newkeylist_t)(void);
00108 typedef void (*pSOIFn_freekeylist_t)(KEY **);
00109 typedef void (*pSOIFn_setkey_str_t)(KEY **, char *, char *);
00110 typedef void (*pSOIFn_setkey_int_t)(KEY **, char *, int);
00111 typedef char *(*pSOIFn_getkey_str_t)(KEY *, const char *);
00112 typedef int (*pSOIFn_getkey_int_t)(KEY *, const char *);
00113 typedef int (*pSOIFn_parse_list_t)(KEY **, char *);
00114 typedef int (*pSOIFn_keyiterate_t)(void (*action)(), KEY *overlist);
00115 typedef void *(*pSOIFn_sds_data_t)(SDS *);
00116 typedef void (*pSOIFn_sds_free_data_t)(SDS *);
00117 typedef int (*pSOIFn_sds_datatype_t)(SDS *);
00118 typedef long (*pSOIFn_sds_data_length_t)(SDS *);
00119 typedef int (*pSOIFn_sds_numbytes_t)(SDS *);
00120 typedef int (*pSOIFn_sds_rank_t)(SDS *);
00121 typedef int *(*pSOIFn_sds_length_t)(SDS *);
00122 typedef ATTRIBUTES *(*pSOIFn_sds_first_attr_t)(SDS *);
00123 typedef ATTRIBUTES *(*pSOIFn_sds_next_attr_t)(ATTRIBUTES *);
00124 typedef ATTRIBUTES *(*pSOIFn_sds_last_attr_t)(SDS *);
00125 typedef char *(*pSOIFn_sds_attrname_t)(ATTRIBUTES *);
00126 typedef int (*pSOIFn_sds_attrtype_t)(ATTRIBUTES *);
00127 typedef void *(*pSOIFn_sds_attrvalue_t)(ATTRIBUTES *);
00128 typedef char *(*pSOIFn_sds_attrcomment_t)(ATTRIBUTES *);
00129 typedef SDS * (*pSOIFn_sds_get_fits_head_t)(char *);
00130 typedef void (*pSOIFn_sds_free_t)(SDS **);
00131 typedef SDS * (*pSOIFn_sds_read_fits_t)(FILE *);
00132
00133
00134 void **gpFn = NULL;
00135
00136
00137 struct hsearch_data *ftable = NULL;
00138 HContainer_t *htable = NULL;
00139
00140 const int kDSDS_MaxFunctions = 128;
00141 const int kDSDS_MaxKeyName = 1024;
00142 const int kDSDS_MaxHandles = 4096;
00143
00144 const int kDSDS_MaxVDSs = 256;
00145
00146
00147 void DSDS_free_keylistarr(DSDS_KeyList_t ***pklarr, int n);
00148 void DSDS_free_segarr(DRMS_Segment_t **psarr, int n);
00149
00150 static void *GetSOI(kDSDS_Stat_t *stat)
00151 {
00152 static int attempted = 0;
00153 kDSDS_Stat_t status;
00154
00155 if (!attempted && !gHandleSOI)
00156 {
00157
00158 gHandleSOI = DSDS_GetLibHandle(kLIBSOI, &status);
00159 if (status == kDSDS_Stat_CantOpenLibrary)
00160 {
00161 status = kDSDS_Stat_NoSOI;
00162 }
00163
00164 attempted = 1;
00165 }
00166
00167 if (gHandleSOI)
00168 {
00169 status = kDSDS_Stat_Success;
00170 }
00171 else
00172 {
00173 status = kDSDS_Stat_NoSOI;
00174 }
00175
00176 if (stat)
00177 {
00178 *stat = status;
00179 }
00180
00181 return gHandleSOI;
00182 }
00183
00184 static void *GetSOIFPtr(void *hSOI, Soifn_t fnNum)
00185 {
00186 void *ret = NULL;
00187 char *msg = NULL;
00188 int err = 0;
00189
00190 if (hSOI)
00191 {
00192 if (!ftable)
00193 {
00194 ftable = (struct hsearch_data *)malloc(sizeof(struct hsearch_data));
00195 gpFn = (void **)malloc(sizeof(void *) * kDSDS_MaxFunctions);
00196 memset(ftable, 0, sizeof(struct hsearch_data));
00197 memset(gpFn, 0, sizeof(void *) * kDSDS_MaxFunctions);
00198
00199 if (hcreate_r(kDSDS_MaxFunctions, ftable))
00200 {
00201 ENTRY entry;
00202 ENTRY *entryRet = NULL;
00203 int nfn;
00204
00205 for (nfn = 0; err == 0 && nfn < kSOI_NFNS; nfn++)
00206 {
00207 entry.key = SoifnNames[nfn];
00208 entry.data = &(gpFn[nfn]);
00209 if (!hsearch_r(entry, ENTER, &entryRet, ftable))
00210 {
00211 err = 1;
00212 }
00213 }
00214 }
00215 }
00216 }
00217
00218 if (!err && ftable)
00219 {
00220 ENTRY entrySearch;
00221 ENTRY *entryFound = NULL;
00222
00223 entrySearch.key = SoifnNames[fnNum];
00224 hsearch_r(entrySearch, FIND, &entryFound, ftable);
00225 if (!entryFound)
00226 {
00227 fprintf(stderr, "Symbol %s not found in ftable.\n", SoifnNames[fnNum]);
00228 err = 1;
00229 }
00230 else
00231 {
00232 void **pFn = entryFound->data;
00233
00234 if (*pFn == NULL)
00235 {
00236
00237 dlerror();
00238 ret = dlsym(hSOI, SoifnNames[fnNum]);
00239 if ((msg = dlerror()) != NULL)
00240 {
00241
00242 fprintf(stderr, "Symbol %s not found: %s.\n", SoifnNames[fnNum], msg);
00243 ret = NULL;
00244 err = 1;
00245 }
00246
00247 if (ret)
00248 {
00249 *pFn = ret;
00250 }
00251 }
00252 else
00253 {
00254 ret = *pFn;
00255 }
00256 }
00257 }
00258
00259 return ret;
00260 }
00261
00262 static void freeVDS(const void *value)
00263 {
00264 kDSDS_Stat_t status = kDSDS_Stat_Success;
00265
00266 VDS *tofree = *((VDS **)value);
00267 if (tofree)
00268 {
00269 void *hSOI = GetSOI(&status);
00270
00271 if (hSOI)
00272 {
00273 pSOIFn_vds_close_t pFn_vds_close = (pSOIFn_vds_close_t)GetSOIFPtr(hSOI, kSOI_VDS_CLOSE);
00274
00275 if (pFn_vds_close)
00276 {
00277 (*pFn_vds_close)(&tofree);
00278 }
00279 }
00280 }
00281 }
00282
00283
00284 static HContainer_t *getVDSCache(kDSDS_Stat_t *rstat)
00285 {
00286 kDSDS_Stat_t status = kDSDS_Stat_Success;
00287
00288 if (!gHandleVDSCache)
00289 {
00290
00291 gHandleVDSCache = hcon_create(sizeof(VDS *), kDSDS_MaxHandle, freeVDS, NULL, NULL, NULL, 0);
00292 if (!gHandleVDSCache)
00293 {
00294 status = kDSDS_Stat_NoMemory;
00295 }
00296 }
00297
00298 if (rstat)
00299 {
00300 *rstat = status;
00301 }
00302
00303 return gHandleVDSCache;
00304 }
00305
00306 static void purgeVDSCache()
00307 {
00308
00309 int initSize;
00310 HIterator_t iter;
00311 const char *key = NULL;
00312 int ielem;
00313
00314 if (gHandleVDSCache)
00315 {
00316 initSize = hcon_size(gHandleVDSCache);
00317 hiter_new(&iter, gHandleVDSCache);
00318 ielem = 0;
00319
00320 while (hcon_size(gHandleVDSCache) > initSize / 2)
00321 {
00322
00323 key = iter.elems[ielem]->key;
00324 hcon_remove(gHandleVDSCache, key);
00325 ielem++;
00326 }
00327 }
00328 }
00329
00330 static int isfullVDSCache()
00331 {
00332 if (gHandleVDSCache)
00333 {
00334 return hcon_size(gHandleVDSCache) >= kDSDS_MaxVDSs;
00335 }
00336
00337 return 0;
00338 }
00339
00340 static int insertVDSIntoCache(DSDS_Handle_t handle, VDS *vds)
00341 {
00342 kDSDS_Stat_t status = kDSDS_Stat_Success;
00343 HContainer_t *cache = NULL;
00344
00345 cache = getVDSCache(&status);
00346
00347 if (cache && status == kDSDS_Stat_Success)
00348 {
00349 if (isfullVDSCache())
00350 {
00351 purgeVDSCache();
00352 }
00353
00354 if (hcon_insert(cache, handle, &vds) != 0)
00355 {
00356 status = kDSDS_Stat_VDSCache;
00357 }
00358 }
00359
00360 return status;
00361 }
00362
00363 static VDS *getVDSFromCache(DSDS_Handle_t handle)
00364 {
00365 if (gHandleVDSCache)
00366 {
00367 VDS **pVds = (VDS **)hcon_lookup(gHandleVDSCache, handle);
00368
00369 if (pVds)
00370 {
00371 return *(pVds);
00372 }
00373 }
00374
00375 return NULL;
00376 }
00377
00378
00379 static VDS *getVDS(KEY *keylist, const char *dsname, DSDS_Handle_t handle, kDSDS_Stat_t *rstat)
00380 {
00381 VDS *vds = NULL;
00382 kDSDS_Stat_t status;
00383 void *hSOI = NULL;
00384
00385 status = kDSDS_Stat_Success;
00386
00387 vds = getVDSFromCache(handle);
00388
00389 if (!vds)
00390 {
00391 hSOI = GetSOI(&status);
00392
00393 if (hSOI)
00394 {
00395 pSOIFn_vds_open_t pFn_vds_open = (pSOIFn_vds_open_t)GetSOIFPtr(hSOI, kSOI_VDS_OPEN);
00396 vds = (*pFn_vds_open)(keylist, dsname);
00397
00398 if (vds)
00399 {
00400
00401 insertVDSIntoCache(handle, vds);
00402 }
00403 }
00404 }
00405
00406 if (rstat)
00407 {
00408 *rstat = status;
00409 }
00410
00411 return vds;
00412 }
00413
00414 static void removeVDSFromCache(DSDS_Handle_t handle)
00415 {
00416 if (gHandleVDSCache)
00417 {
00418 hcon_remove(gHandleVDSCache, handle);
00419 }
00420 }
00421
00422 static void destroyVDSCache()
00423 {
00424 if (gHandleVDSCache)
00425 {
00426 hcon_destroy(&gHandleVDSCache);
00427 }
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 static int GenerateHandle(const char *desc, void *structure, DSDS_pHandle_t out)
00441 {
00442 char buf[kDSDS_MaxHandle];
00443 snprintf(buf, sizeof(buf), "%s:%p", desc, structure);
00444 int err = 0;
00445
00446
00447 if (!htable)
00448 {
00449 htable = hcon_create(kDSDS_MaxHandle, kDSDS_MaxHandle, NULL, NULL, NULL, NULL, 0);
00450 }
00451
00452 if (htable)
00453 {
00454 err = hcon_insert(htable, buf, buf);
00455
00456 if (!err)
00457 {
00458 void *item = hcon_lookup(htable, buf);
00459 if (item)
00460 {
00461 *out = (DSDS_Handle_t)item;
00462 }
00463 else
00464 {
00465 err = 1;
00466 }
00467 }
00468 }
00469 else
00470 {
00471 err = 1;
00472 }
00473
00474 return err;
00475 }
00476
00477 static DSDS_Handle_t FindHandle(const char *desc)
00478 {
00479 DSDS_Handle_t ret = NULL;
00480
00481 if (htable)
00482 {
00483 void *item = hcon_lookup(htable, desc);
00484 if (item)
00485 {
00486 ret = (DSDS_Handle_t)item;
00487 }
00488 }
00489
00490 return ret;
00491 }
00492
00493 static int GetStructure(DSDS_Handle_t handle, void **out)
00494 {
00495 void *structure = NULL;
00496 char *handleStr = NULL;
00497 char *pCh = NULL;
00498 int err = 1;
00499
00500 if (handle && out && htable)
00501 {
00502
00503 void *item = hcon_lookup(htable, handle);
00504
00505 if (!item)
00506 {
00507 fprintf(stderr, "Invalid DSDS_Handle %s.\n", handle);
00508 err = 1;
00509 }
00510 else
00511 {
00512 handleStr = strdup((const char *)handle);
00513 if (handleStr)
00514 {
00515 pCh = strchr(handleStr, ':');
00516 if (pCh)
00517 {
00518 pCh++;
00519 if (pCh < handleStr + strlen(handleStr))
00520 {
00521 if (sscanf(pCh, "%p", &structure) == 1)
00522 {
00523 *out = structure;
00524 err = 0;
00525 }
00526 }
00527 }
00528 }
00529 }
00530 }
00531
00532 if (handleStr)
00533 {
00534 free(handleStr);
00535 }
00536
00537 return err;
00538 }
00539
00540 static void DestroyHandle(DSDS_pHandle_t h)
00541 {
00542 if (h && *h)
00543 {
00544 void *item = hcon_lookup(htable, *h);
00545 if (item)
00546 {
00547 KEY *keylist = NULL;
00548 pSOIFn_freekeylist_t pFn_freekeylist = NULL;
00549 void *hSOI = NULL;
00550 kDSDS_Stat_t status;
00551
00552 hSOI = GetSOI(&status);
00553
00554 if (hSOI)
00555 {
00556 pFn_freekeylist = (pSOIFn_freekeylist_t)GetSOIFPtr(hSOI, kSOI_FREEKEYLIST);
00557 }
00558
00559
00560 if (pFn_freekeylist)
00561 {
00562
00563 GetStructure(*h, (void **)&keylist);
00564 (*pFn_freekeylist)(&keylist);
00565 }
00566
00567
00568 hcon_remove(htable, *h);
00569 free(*h);
00570 *h = NULL;
00571 }
00572 }
00573 }
00574
00575 static void Printkey(KEY *key)
00576 {
00577 printf ("%s:\t", key->name);
00578 switch(key->type) {
00579 case KEYTYP_STRING:
00580 printf ("KEYTYP_STRING\t");
00581 printf ("%s\n", (char *) key->val);
00582 break;
00583 case KEYTYP_BYTE:
00584 printf ("KEYTYP_BYTE\t");
00585 printf ("%d\n", *(char *)key->val);
00586 break;
00587 case KEYTYP_INT:
00588 printf ("KEYTYP_INT\t");
00589 printf ("%d\n", *(int *)key->val);
00590 break;
00591 case KEYTYP_FLOAT:
00592 printf ("KEYTYP_FLOAT\t");
00593 printf ("%13.6e\n", *(float *)key->val);
00594 break;
00595 case KEYTYP_DOUBLE:
00596 printf ("KEYTYP_DOUBLE\t");
00597 printf ("%23.16e\n", *(double *)key->val);
00598 break;
00599 case KEYTYP_TIME:
00600 printf ("KEYTYP_TIME\t");
00601 printf ("%23.16e\n", *(TIME *)key->val);
00602 break;
00603 case KEYTYP_SHORT:
00604 printf ("KEYTYP_SHORT\t");
00605 printf ("%d\n", *(short *)key->val);
00606 break;
00607 case KEYTYP_LONG:
00608 printf ("KEYTYP_LONG\t");
00609 printf ("%ld\n", *(long *)key->val);
00610 break;
00611 case KEYTYP_UBYTE:
00612 printf ("KEYTYP_UBYTE\t");
00613 printf ("%d\n", *(unsigned char *)key->val);
00614 break;
00615 case KEYTYP_USHORT:
00616 printf ("KEYTYP_USHORT\t");
00617 printf ("%d\n", *(unsigned short *)key->val);
00618 break;
00619 case KEYTYP_UINT:
00620 printf ("KEYTYP_UINT\t");
00621 printf ("%u\n", *(unsigned int *)key->val);
00622 break;
00623 case KEYTYP_ULONG:
00624 printf ("KEYTYP_ULONG\t");
00625 printf ("%lu\n", *(unsigned long *)key->val);
00626 break;
00627 default:
00628 printf ("(void)\n");
00629 }
00630 }
00631
00632
00633 static KEY *CreateSOIKeylist(const char *progspec, LinkedList_t **wdlist, kDSDS_Stat_t *stat)
00634 {
00635 kDSDS_Stat_t status = kDSDS_Stat_Success;
00636 void *hSOI = GetSOI(&status);
00637 KEY *ret = NULL;
00638 int err = NO_ERROR;
00639
00640 if (hSOI)
00641 {
00642 pSOIFn_newkeylist_t pFn_newkeylist =
00643 (pSOIFn_newkeylist_t)GetSOIFPtr(hSOI, kSOI_NEWKEYLIST);
00644 pSOIFn_freekeylist_t pFn_freekeylist =
00645 (pSOIFn_freekeylist_t)GetSOIFPtr(hSOI, kSOI_FREEKEYLIST);
00646 pSOIFn_setkey_str_t pFn_setkey_str =
00647 (pSOIFn_setkey_str_t)GetSOIFPtr(hSOI, kSOI_SETKEY_STR);
00648 pSOIFn_setkey_int_t pFn_setkey_int =
00649 (pSOIFn_setkey_int_t)GetSOIFPtr(hSOI, kSOI_SETKEY_INT);
00650 pSOIFn_getkey_int_t pFn_getkey_int =
00651 (pSOIFn_getkey_int_t)GetSOIFPtr(hSOI, kSOI_GETKEY_INT);
00652 pSOIFn_parse_list_t pFn_parse_list =
00653 (pSOIFn_parse_list_t)GetSOIFPtr(hSOI, kSOI_PARSE_LIST);
00654 pSOIFn_keyiterate_t pFn_keyiterate =
00655 (pSOIFn_keyiterate_t)GetSOIFPtr(hSOI, kSOI_KEYITERATE);
00656
00657 KEY *dslist = NULL;
00658 char *spec = strdup(progspec);
00659
00660 if (spec && pFn_parse_list && pFn_newkeylist &&
00661 pFn_freekeylist && pFn_setkey_str &&
00662 pFn_getkey_int && pFn_setkey_int)
00663 {
00664 dslist = (*pFn_newkeylist)();
00665
00666 (*pFn_setkey_str)(&dslist, "in", spec);
00667 if ((err = (*pFn_parse_list)(&dslist, "in")) != NO_ERROR)
00668 {
00669 fprintf(stderr, "Error calling parse_list(): %d.\n", err);
00670 status = kDSDS_Stat_APIRetErr;
00671 }
00672
00673
00674
00675 if (DSDS_IsDSDSSpec(spec) || DSDS_IsDSDSPort(spec))
00676 {
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 int infd[2];
00688 int oldstdin, oldstdout;
00689
00690
00691 pipe(infd);
00692
00693 oldstdin = dup(0);
00694 oldstdout = dup(1);
00695
00696
00697
00698
00699
00700 dup2(infd[1], 1);
00701
00702 if(!fork())
00703 {
00704
00705 char **argv = malloc(sizeof(char *) * 3);
00706 argv[0] = "peq";
00707 argv[1] = spec;
00708 argv[2] = NULL;
00709
00710
00711
00712
00713 close(infd[0]);
00714 close(infd[1]);
00715
00716 execvp(argv[0], argv);
00717 }
00718 else
00719 {
00720
00721 close(0);
00722 close(1);
00723 dup2(oldstdin, 0);
00724 dup2(oldstdout, 1);
00725
00726
00727 close(infd[1]);
00728
00729 char buf;
00730 char lineBuf[LINE_MAX];
00731 long nRead = 0;
00732 int nGot = 0;
00733 int nds = 0;
00734
00735 while (read(infd[0], (void *)&buf, 1) > 0)
00736 {
00737 if (buf == '\n')
00738 {
00739 if (nRead < LINE_MAX && nRead > 0)
00740 {
00741
00742 char *keystr = NULL;
00743 char *typstr = NULL;
00744 char *valstr = NULL;
00745 int valint = 0;
00746 char *colon = NULL;
00747 long long ds = 0;
00748
00749 lineBuf[nRead] = '\0';
00750
00751 if (strstr(lineBuf, "is not on-line"))
00752 {
00753
00754 status = kDSDS_Stat_DSDSOffline;
00755 break;
00756 }
00757
00758 keystr = strtok(lineBuf, " \t");
00759
00760 if (keystr)
00761 {
00762 if (strstr(keystr, "_wd:") && sscanf(keystr, "in_%lld_wd", &ds))
00763 {
00764
00765 if ((colon = strchr(keystr, ':')) != NULL)
00766 {
00767 *colon = '\0';
00768
00769 typstr = strtok(NULL, " \t");
00770 if (typstr)
00771 {
00772 if (!strcmp(typstr, "KEYTYP_STRING"))
00773 {
00774 valstr = strtok(NULL, " \t");
00775 (*pFn_setkey_str)(&dslist, keystr, valstr);
00776
00777
00778 if (wdlist && !*wdlist)
00779 {
00780 *wdlist = list_llcreate(PATH_MAX, NULL);
00781 }
00782
00783 if (*wdlist)
00784 {
00785 list_llinserthead(*wdlist, valstr);
00786 }
00787
00788 nGot++;
00789 }
00790 }
00791 }
00792 }
00793 else if ((strstr(keystr, "_level_sn:") &&
00794 sscanf(keystr, "in_%lld_level_sn", &ds)) ||
00795 (strstr(keystr, "_series_sn:") &&
00796 sscanf(keystr, "in_%lld_series_sn", &ds)))
00797 {
00798 if ((colon = strchr(keystr, ':')) != NULL)
00799 {
00800 *colon = '\0';
00801
00802 typstr = strtok(NULL, " \t");
00803 if (typstr)
00804 {
00805 if (!strcmp(typstr, "KEYTYP_INT"))
00806 {
00807 valstr = strtok(NULL, " \t");
00808 valint = atoi(valstr);
00809 (*pFn_setkey_int)(&dslist, keystr, valint);
00810 nGot++;
00811 }
00812 }
00813 }
00814 }
00815 }
00816
00817 nRead = 0;
00818 }
00819 }
00820 else if (nRead < LINE_MAX)
00821 {
00822 lineBuf[nRead] = buf;
00823 nRead++;
00824 }
00825 }
00826
00827 close(infd[0]);
00828
00829 if (status == kDSDS_Stat_Success)
00830 {
00831 if (DSDS_IsDSDSSpec(spec))
00832 {
00833
00834
00835 nds = (*pFn_getkey_int)(dslist, "in_nsets");
00836 if (nGot != 3 * nds)
00837 {
00838 status = kDSDS_Stat_PeqError;
00839 }
00840 }
00841 }
00842 }
00843 }
00844
00845 if (status == kDSDS_Stat_Success)
00846 {
00847
00848
00849
00850
00851
00852
00853 if (DSDS_IsDSDSPort(spec))
00854 {
00855 (*pFn_freekeylist)(&dslist);
00856 dslist = (*pFn_newkeylist)();
00857
00858
00859 if (wdlist && *wdlist)
00860 {
00861 char *sumsdir = (char *)(list_llgethead(*wdlist)->data);
00862 char *tmp = NULL;
00863
00864
00865
00866
00867 if (sumsdir[strlen(sumsdir) - 1] != '/')
00868 {
00869 tmp = malloc(strlen(sumsdir) + 1);
00870 if (tmp)
00871 {
00872 sprintf(tmp, "%s/", sumsdir);
00873 }
00874 }
00875 else
00876 {
00877 tmp = strdup(sumsdir);
00878 }
00879
00880 if (tmp)
00881 {
00882 (*pFn_setkey_str)(&dslist, "in", tmp);
00883 free(tmp);
00884 tmp = NULL;
00885 }
00886
00887 if ((err = (*pFn_parse_list)(&dslist, "in")) != NO_ERROR)
00888 {
00889 fprintf(stderr, "Error calling parse_list(): %d.\n", err);
00890 status = kDSDS_Stat_APIRetErr;
00891 }
00892 }
00893 else
00894 {
00895 status = kDSDS_Stat_PeqError;
00896 fprintf(stderr, "peq failed to find the SUMS directory containing the data files.\n");
00897 }
00898 }
00899 else if (!DSDS_IsDSDSSpec(spec))
00900 {
00901
00902
00903 if (wdlist && !*wdlist)
00904 {
00905 *wdlist = list_llcreate(PATH_MAX, NULL);
00906 }
00907
00908 if (*wdlist)
00909 {
00910 char tbuf[PATH_MAX];
00911
00912 snprintf(tbuf, sizeof(tbuf), "%s", spec);
00913 list_llinserthead(*wdlist, tbuf);
00914 }
00915 }
00916 }
00917 }
00918 else
00919 {
00920 status = kDSDS_Stat_MissingAPI;
00921 }
00922
00923 if (status == kDSDS_Stat_Success)
00924 {
00925 ret = dslist;
00926
00927 }
00928
00929 if (spec)
00930 {
00931 free(spec);
00932 }
00933 }
00934
00935 if (stat)
00936 {
00937 *stat = status;
00938 }
00939
00940 return ret;
00941 }
00942
00943
00944
00945
00946 static DRMS_Type_t SOITypeToDRMSType(int soiType)
00947 {
00948 DRMS_Type_t drmsType;
00949
00950 switch (soiType)
00951 {
00952 case SDS_LOGICAL:
00953 case SDS_BYTE:
00954 case SDS_UBYTE:
00955 drmsType = DRMS_TYPE_CHAR;
00956 break;
00957 case SDS_SHORT:
00958 case SDS_USHORT:
00959 drmsType = DRMS_TYPE_SHORT;
00960 break;
00961 case SDS_INT:
00962 case SDS_UINT:
00963 drmsType = DRMS_TYPE_INT;
00964 break;
00965 case SDS_LONG:
00966 case SDS_ULONG:
00967 drmsType = DRMS_TYPE_LONGLONG;
00968 break;
00969 case SDS_FLOAT:
00970 drmsType = DRMS_TYPE_FLOAT;
00971 break;
00972 case SDS_DOUBLE:
00973 drmsType = DRMS_TYPE_DOUBLE;
00974 break;
00975 case SDS_TIME:
00976 drmsType = DRMS_TYPE_TIME;
00977 break;
00978 case SDS_STRING:
00979 drmsType = DRMS_TYPE_STRING;
00980 break;
00981 default:
00982 drmsType = DRMS_TYPE_RAW;
00983 }
00984
00985 return drmsType;
00986 }
00987
00988
00989
00990
00991
00992
00993
00994 int PolyValueToDRMSValue(int soiType, void *val, DRMS_Type_Value_t *value)
00995 {
00996 int error = 0;
00997
00998 switch (soiType)
00999 {
01000 case SDS_LOGICAL:
01001 value->char_val = *((char *)val);
01002 break;
01003 case SDS_BYTE:
01004 value->char_val = *((signed char *)val);
01005 break;
01006 case SDS_UBYTE:
01007 value->char_val = *((unsigned char *)val);
01008 break;
01009 case SDS_SHORT:
01010 value->short_val = *((short *)val);
01011 break;
01012 case SDS_USHORT:
01013 value->short_val = *((unsigned short *)val);
01014 break;
01015 case SDS_INT:
01016 value->int_val = *((int *)val);
01017 break;
01018 case SDS_UINT:
01019 value->int_val = *((unsigned int *)val);
01020 break;
01021 case SDS_LONG:
01022
01023
01024 {
01025 long longval = *((long *)val);
01026 value->longlong_val = (long long)longval;
01027 }
01028 break;
01029 case SDS_ULONG:
01030
01031
01032 {
01033 long longval = *((unsigned long *)val);
01034 value->longlong_val = (long long)longval;
01035 }
01036 break;
01037 case SDS_FLOAT:
01038 value->float_val = *((float *)val);
01039 break;
01040 case SDS_DOUBLE:
01041 value->double_val = *((double *)val);
01042 break;
01043 case SDS_TIME:
01044 value->time_val = *((double *)val);
01045 break;
01046 case SDS_STRING:
01047 value->string_val = strdup((char *)val);
01048 if (value->string_val == NULL)
01049 {
01050 fprintf(stderr, "alloc failure in PolyValueToDRMSValue().\n");
01051 error = 1;
01052 }
01053 break;
01054 default:
01055 fprintf(stderr, "Invalid soi type: %d\n", soiType);
01056 error = 1;
01057 }
01058
01059 return error;
01060 }
01061
01062 static int GetKWFormat(char *buf, int size, DRMS_Type_t drmsType)
01063 {
01064 int error = 0;
01065 char formatStr[64];
01066
01067 switch (drmsType)
01068 {
01069 case DRMS_TYPE_CHAR:
01070 formatStr[0] = '%';
01071 formatStr[1] = 'd';
01072 formatStr[2] = '\0';
01073 break;
01074 case DRMS_TYPE_SHORT:
01075 formatStr[0] = '%';
01076 formatStr[1] = 'd';
01077 formatStr[2] = '\0';
01078 break;
01079 case DRMS_TYPE_INT:
01080 formatStr[0] = '%';
01081 formatStr[1] = 'd';
01082 formatStr[2] = '\0';
01083 break;
01084 case DRMS_TYPE_LONGLONG:
01085 formatStr[0] = '%';
01086 formatStr[1] = 'l';
01087 formatStr[2] = 'l';
01088 formatStr[3] = 'd';
01089 formatStr[4] = '\0';
01090 break;
01091 case DRMS_TYPE_FLOAT:
01092 formatStr[0] = '%';
01093 formatStr[1] = 'f';
01094 formatStr[2] = '\0';
01095 break;
01096 case DRMS_TYPE_DOUBLE:
01097 formatStr[0] = '%';
01098 formatStr[1] = 'f';
01099 formatStr[2] = '\0';
01100 break;
01101 case DRMS_TYPE_TIME:
01102 snprintf(formatStr, sizeof(formatStr), "%s", "UTC");
01103 break;
01104 case DRMS_TYPE_STRING:
01105 formatStr[0] = '%';
01106 formatStr[1] = 's';
01107 formatStr[2] = '\0';
01108 break;
01109 default:
01110 fprintf(stderr, "Invalid drms type: %d\n", (int)drmsType);
01111 error = 1;
01112 }
01113
01114 if (!error)
01115 {
01116 snprintf(buf, size, "%s", formatStr);
01117 }
01118
01119 return error;
01120 }
01121
01122 static long long NumRecords(void *hSOI, int nds, KEY *params, kDSDS_Stat_t *stat)
01123 {
01124 long long nRecs = 0;
01125 char dsname[kDSDS_MaxKeyName];
01126 char key[kDSDS_MaxKeyName];
01127 int ds;
01128 int fsn = 0;
01129 int lsn = 0;
01130 kDSDS_Stat_t status = kDSDS_Stat_Success;
01131 VDS *vds = NULL;
01132
01133 pSOIFn_vds_open_t pFn_vds_open =
01134 (pSOIFn_vds_open_t)GetSOIFPtr(hSOI, kSOI_VDS_OPEN);
01135 pSOIFn_vds_close_t pFn_vds_close =
01136 (pSOIFn_vds_close_t)GetSOIFPtr(hSOI, kSOI_VDS_CLOSE);
01137 pSOIFn_vds_last_record_t pFn_vds_last_record =
01138 (pSOIFn_vds_last_record_t)GetSOIFPtr(hSOI, kSOI_VDS_LAST_RECORD);
01139 pSOIFn_getkey_int_t pFn_getkey_int =
01140 (pSOIFn_getkey_int_t)GetSOIFPtr(hSOI, kSOI_GETKEY_INT);
01141
01142 if (pFn_vds_open && pFn_vds_close && pFn_vds_last_record &&
01143 pFn_getkey_int)
01144 {
01145
01146 for (ds = 0; ds < nds; ds++)
01147 {
01148 sprintf(dsname, "in_%d", ds);
01149 vds = (*pFn_vds_open)(params, dsname);
01150
01151 if (vds)
01152 {
01153 sprintf(key, "%s_fsn", dsname);
01154 fsn = (*pFn_getkey_int)(params, key);
01155 sprintf(key, "%s_lsn", dsname);
01156 lsn = (*pFn_getkey_int)(params, key);
01157
01158 if (lsn == -1)
01159 {
01160 lsn = (*pFn_vds_last_record)(vds);
01161 }
01162
01163 nRecs += (lsn - fsn + 1);
01164
01165 (*pFn_vds_close)(&vds);
01166 }
01167 }
01168 }
01169 else
01170 {
01171 status = kDSDS_Stat_MissingAPI;
01172 }
01173
01174 if (stat)
01175 {
01176 *stat = status;
01177 }
01178
01179 return nRecs;
01180 }
01181
01182 static void MakeDRMSSeriesName(void *hSOI,
01183 char *drmsSeriesName,
01184 int size,
01185 KEY *params,
01186 const char *dsname,
01187 kDSDS_Stat_t *stat)
01188 {
01189 kDSDS_Stat_t status = kDSDS_Stat_Success;
01190
01191 char drmsLev[DRMS_MAXSERIESNAMELEN];
01192 char key[kDSDS_MaxKeyName];
01193 const char *dsdsNsPrefix = NULL;
01194
01195 pSOIFn_getkey_str_t pFn_getkey_str =
01196 (pSOIFn_getkey_str_t)GetSOIFPtr(hSOI, kSOI_GETKEY_STR);
01197
01198 if (pFn_getkey_str)
01199 {
01200 dsdsNsPrefix = DSDS_GetNsPrefix();
01201
01202 snprintf(key, sizeof(key), "%s_prog", dsname);
01203 char *prog = (*pFn_getkey_str)(params, key);
01204 snprintf(key, sizeof(key), "%s_series", dsname);
01205 char *dsdsSeries = (*pFn_getkey_str)(params, key);
01206 snprintf(key, sizeof(key), "%s_level", dsname);
01207 char *level = (*pFn_getkey_str)(params, key);
01208 char *dot = NULL;
01209
01210 if (prog && dsdsSeries && level)
01211 {
01212 snprintf(drmsLev, sizeof(drmsLev), "%s", level);
01213
01214 if ((dot = strchr(drmsLev, '.')) != NULL)
01215 {
01216 *dot = '_';
01217 }
01218
01219 snprintf(drmsSeriesName,
01220 size,
01221 "%s_%s.%s_%s__%lld",
01222 dsdsNsPrefix,
01223 prog,
01224 dsdsSeries,
01225 drmsLev,
01226 gSeriesGuid);
01227 }
01228 else
01229 {
01230
01231
01232 snprintf(drmsSeriesName, size, "%s.%s%lld", dsdsNsPrefix, kDSDS_GenericSeriesName, gSeriesGuid);
01233 }
01234
01235 gSeriesGuid++;
01236 }
01237 else
01238 {
01239 status = kDSDS_Stat_MissingAPI;
01240 }
01241
01242 if (stat)
01243 {
01244 *stat = status;
01245 }
01246 }
01247
01248 static void FreeDSDSKeyList(DSDS_KeyList_t **list)
01249 {
01250 DSDS_KeyList_t *pList = *list;
01251 DSDS_KeyList_t *nElem = NULL;
01252
01253 while (pList)
01254 {
01255 nElem = pList->next;
01256
01257
01258 if (pList->elem)
01259 {
01260 if (pList->elem->info->type == DRMS_TYPE_STRING && pList->elem->value.string_val)
01261 {
01262 free(pList->elem->value.string_val);
01263 }
01264
01265 if (pList->elem->info)
01266 {
01267 free (pList->elem->info);
01268 }
01269
01270 free(pList->elem);
01271 }
01272 free(pList);
01273 pList = nElem;
01274 }
01275
01276 *list = NULL;
01277 }
01278
01279
01280 static int LoopAttrs(void *hSOI,
01281 SDS *sds,
01282 DSDS_KeyList_t *pHead,
01283 kDSDS_Stat_t *stat,
01284 char **datafile,
01285 int dfnlen)
01286 {
01287 kDSDS_Stat_t status = kDSDS_Stat_Success;
01288 int nAttrs = 0;
01289
01290 if (sds && pHead && hSOI)
01291 {
01292 pSOIFn_sds_first_attr_t pFn_sds_first_attr =
01293 (pSOIFn_sds_first_attr_t)GetSOIFPtr(hSOI, kSOI_SDS_FIRST_ATTR);
01294 pSOIFn_sds_next_attr_t pFn_sds_next_attr =
01295 (pSOIFn_sds_next_attr_t)GetSOIFPtr(hSOI, kSOI_SDS_NEXT_ATTR);
01296 pSOIFn_sds_last_attr_t pFn_sds_last_attr =
01297 (pSOIFn_sds_last_attr_t)GetSOIFPtr(hSOI, kSOI_SDS_LAST_ATTR);
01298 pSOIFn_sds_attrname_t pFn_sds_attrname =
01299 (pSOIFn_sds_attrname_t)GetSOIFPtr(hSOI, kSOI_SDS_ATTRNAME);
01300 pSOIFn_sds_attrtype_t pFn_sds_attrtype =
01301 (pSOIFn_sds_attrtype_t)GetSOIFPtr(hSOI, kSOI_SDS_ATTRTYPE);
01302 pSOIFn_sds_attrvalue_t pFn_sds_attrvalue =
01303 (pSOIFn_sds_attrvalue_t)GetSOIFPtr(hSOI, kSOI_SDS_ATTRVALUE);
01304 pSOIFn_sds_attrcomment_t pFn_sds_attrcomment =
01305 (pSOIFn_sds_attrcomment_t)GetSOIFPtr(hSOI, kSOI_SDS_ATTRCOMMENT);
01306
01307 if (pFn_sds_first_attr &&
01308 pFn_sds_next_attr && pFn_sds_last_attr &&
01309 pFn_sds_attrname && pFn_sds_attrtype &&
01310 pFn_sds_attrvalue && pFn_sds_attrcomment)
01311 {
01312 DSDS_KeyList_t *pKL = pHead;
01313 DSDS_KeyList_t *pPrevKL = NULL;
01314
01315 char *attrName = NULL;
01316 int attrType;
01317 void *attrVal = NULL;
01318 char *attrComment = NULL;
01319 DRMS_Keyword_t *drmskey = NULL;
01320
01321
01322 if (datafile && *datafile)
01323 {
01324 (*datafile)[0] = '\0';
01325 }
01326
01327 nAttrs = 0;
01328 ATTRIBUTES *attr = (*pFn_sds_first_attr)(sds);
01329 ATTRIBUTES *lastAttr = (*pFn_sds_last_attr)(sds);
01330
01331 while (attr)
01332 {
01333 if (pKL->elem != NULL)
01334 {
01335 pKL->next = (DSDS_KeyList_t *)malloc(sizeof(DSDS_KeyList_t));
01336
01337 if (!(pKL->next))
01338 {
01339 status = kDSDS_Stat_NoMemory;
01340 break;
01341 }
01342
01343 pPrevKL = pKL;
01344 pKL = pKL->next;
01345 pKL->next = NULL;
01346 }
01347
01348 attrName = (*pFn_sds_attrname)(attr);
01349
01350 if (attrName && *attrName)
01351 {
01352 attrType = (*pFn_sds_attrtype)(attr);
01353 attrVal = (*pFn_sds_attrvalue)(attr);
01354 attrComment = (*pFn_sds_attrcomment)(attr);
01355
01356
01357 if (datafile &&
01358 *datafile &&
01359 strcmp(attrName, kDATAFILE) == 0 &&
01360 attrType == SDS_STRING &&
01361 strlen(attrVal) > 0)
01362 {
01363 snprintf(*datafile, dfnlen, "%s", (char *)attrVal);
01364 }
01365
01366
01367 drmskey = (DRMS_Keyword_t *)malloc(sizeof(DRMS_Keyword_t));
01368 memset(drmskey, 0, sizeof(DRMS_Keyword_t));
01369 drmskey->info =
01370 (DRMS_KeywordInfo_t *)malloc(sizeof(DRMS_KeywordInfo_t));
01371 memset(drmskey->info, 0, sizeof(DRMS_KeywordInfo_t));
01372
01373 snprintf(drmskey->info->name, DRMS_MAXKEYNAMELEN, "%s", attrName);
01374 drmskey->info->type = SOITypeToDRMSType(attrType);
01375 if (GetKWFormat(drmskey->info->format,
01376 DRMS_MAXFORMATLEN,
01377 drmskey->info->type))
01378 {
01379 status = kDSDS_Stat_TypeErr;
01380 }
01381 else
01382 {
01383 if (attrComment)
01384 {
01385 snprintf(drmskey->info->description,
01386 DRMS_MAXCOMMENTLEN,
01387 "%s",
01388 attrComment);
01389 }
01390
01391 if (PolyValueToDRMSValue(attrType,
01392 attrVal,
01393 &(drmskey->value)))
01394 {
01395 status = kDSDS_Stat_TypeErr;
01396 }
01397 }
01398
01399 if (status != kDSDS_Stat_Success)
01400 {
01401
01402 fprintf(stderr, "A bad fits keyword encountered.\n"
01403 "Some keywords may not have been ingested.\n");
01404
01405 if (drmskey)
01406 {
01407 if (drmskey->info)
01408 {
01409 free(drmskey->info);
01410 }
01411
01412 free(drmskey);
01413 }
01414
01415 free(pKL);
01416 pKL = pPrevKL;
01417 pKL->next = NULL;
01418 }
01419 else
01420 {
01421 pKL->elem = drmskey;
01422 nAttrs++;
01423 }
01424
01425 if (attr == lastAttr)
01426 {
01427 break;
01428 }
01429 }
01430
01431 attr = (*pFn_sds_next_attr)(attr);
01432
01433 }
01434 }
01435 else
01436 {
01437 status = kDSDS_Stat_MissingAPI;
01438 }
01439 }
01440
01441 if (stat)
01442 {
01443 *stat = status;
01444 }
01445
01446 return nAttrs;
01447 }
01448
01449 static void FillDRMSSeg(void *hSOI,
01450 SDS *sds,
01451 DRMS_Segment_t *segout,
01452 const char *segname,
01453 DRMS_Protocol_t protocol,
01454 const char *filename,
01455 kDSDS_Stat_t *stat)
01456 {
01457 kDSDS_Stat_t status = kDSDS_Stat_InvalidParams;
01458
01459 if (!hSOI)
01460 {
01461 status = kDSDS_Stat_NoSOI;
01462 }
01463 else if (!segout)
01464 {
01465 status = kDSDS_Stat_InvalidParams;
01466 }
01467 else
01468 {
01469 pSOIFn_sds_rank_t pFn_sds_rank =
01470 (pSOIFn_sds_rank_t)GetSOIFPtr(hSOI, kSOI_SDS_RANK);
01471 pSOIFn_sds_length_t pFn_sds_length =
01472 (pSOIFn_sds_length_t)GetSOIFPtr(hSOI, kSOI_SDS_LENGTH);
01473 pSOIFn_sds_datatype_t pFn_sds_datatype =
01474 (pSOIFn_sds_datatype_t)GetSOIFPtr(hSOI, kSOI_SDS_DATATYPE);
01475
01476 if (pFn_sds_rank && pFn_sds_length && pFn_sds_datatype)
01477 {
01478
01479 int rank = (*pFn_sds_rank)(sds);
01480 int *dims = (*pFn_sds_length)(sds);
01481 memset(segout, 0, sizeof(DRMS_Segment_t));
01482 segout->info = (DRMS_SegmentInfo_t *)malloc(sizeof(DRMS_SegmentInfo_t));
01483
01484 if (segout->info)
01485 {
01486 memset(segout->info, 0, sizeof(DRMS_SegmentInfo_t));
01487 snprintf(segout->info->name, DRMS_MAXSEGNAMELEN, "%s", segname);
01488 segout->info->segnum = 0;
01489 segout->info->type = SOITypeToDRMSType((*pFn_sds_datatype)(sds));
01490 segout->info->naxis = rank;
01491 segout->info->protocol = protocol;
01492 segout->info->scope = DRMS_VARIABLE;
01493
01494 memcpy(segout->axis, dims, sizeof(int) * rank);
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504 if (segout->info->type == DRMS_TYPE_INT || segout->info->type == DRMS_TYPE_LONGLONG)
01505 {
01506 segout->info->type = DRMS_TYPE_DOUBLE;
01507 }
01508 else if (segout->info->type == DRMS_TYPE_CHAR || segout->info->type == DRMS_TYPE_SHORT)
01509 {
01510 segout->info->type = DRMS_TYPE_FLOAT;
01511 }
01512
01513 if (filename && *filename)
01514 {
01515 snprintf(segout->filename, DRMS_MAXPATHLEN, "%s", filename);
01516 }
01517
01518 status = kDSDS_Stat_Success;
01519 }
01520 else
01521 {
01522 status = kDSDS_Stat_NoMemory;
01523 }
01524 }
01525 else
01526 {
01527 status = kDSDS_Stat_MissingAPI;
01528 }
01529 }
01530
01531 if (stat)
01532 {
01533 *stat = status;
01534 }
01535 }
01536
01537 static DRMS_Array_t *CreateDRMSArray(void *hSOI, SDS *sds, kDSDS_Stat_t *stat)
01538 {
01539 DRMS_Array_t *ret = NULL;
01540 DRMS_Array_t *local = NULL;
01541 kDSDS_Stat_t status = kDSDS_Stat_Success;
01542
01543 if (hSOI)
01544 {
01545 pSOIFn_sds_data_t pFn_sds_data =
01546 (pSOIFn_sds_data_t)GetSOIFPtr(hSOI, kSOI_SDS_DATA);
01547 pSOIFn_sds_datatype_t pFn_sds_datatype =
01548 (pSOIFn_sds_datatype_t)GetSOIFPtr(hSOI, kSOI_SDS_DATATYPE);
01549 pSOIFn_sds_data_length_t pFn_sds_data_length =
01550 (pSOIFn_sds_data_length_t)GetSOIFPtr(hSOI, kSOI_SDS_DATA_LENGTH);
01551 pSOIFn_sds_numbytes_t pFn_sds_numbytes =
01552 (pSOIFn_sds_numbytes_t)GetSOIFPtr(hSOI, kSOI_SDS_NUMBYTES);
01553 pSOIFn_sds_rank_t pFn_sds_rank =
01554 (pSOIFn_sds_rank_t)GetSOIFPtr(hSOI, kSOI_SDS_RANK);
01555 pSOIFn_sds_length_t pFn_sds_length =
01556 (pSOIFn_sds_length_t)GetSOIFPtr(hSOI, kSOI_SDS_LENGTH);
01557
01558 if (pFn_sds_data && pFn_sds_datatype &&
01559 pFn_sds_data_length && pFn_sds_numbytes &&
01560 pFn_sds_rank && pFn_sds_length)
01561 {
01562
01563 void *data = (*pFn_sds_data)(sds);
01564
01565
01566 local = (DRMS_Array_t *)calloc(1, sizeof(DRMS_Array_t));
01567 if (local)
01568 {
01569 int datasize = (*pFn_sds_numbytes)(sds);
01570 long long datalen = (*pFn_sds_data_length)(sds) * datasize;
01571 local->type = SOITypeToDRMSType((*pFn_sds_datatype)(sds));
01572 local->naxis = (*pFn_sds_rank)(sds);
01573
01574 if (local->naxis < DRMS_MAXRANK)
01575 {
01576 int *dims = (*pFn_sds_length)(sds);
01577 memcpy(local->axis, dims, sizeof(int) * local->naxis);
01578
01579 if (data)
01580 {
01581 local->data = calloc(1, datalen);
01582 if (local->data)
01583 {
01584 memcpy(local->data, data, datalen);
01585 }
01586 else
01587 {
01588 status = kDSDS_Stat_NoMemory;
01589 }
01590 }
01591 }
01592 else
01593 {
01594 fprintf(stderr, "Unsupported data rank %d.\n", local->naxis);
01595 status = kDSDS_Stat_InvalidRank;
01596 }
01597
01598 if (status == kDSDS_Stat_Success)
01599 {
01600
01601 local->bzero = 0.0;
01602 local->bscale = 1.0;
01603 local->israw = 1;
01604
01605
01606
01607
01608
01609
01610
01611
01612 int i;
01613 local->dope[0] = datasize;
01614 for (i = 1; i < local->naxis; i++)
01615 {
01616 local->dope[i] = local->dope[i-1] * local->axis[i-1];
01617 }
01618
01619 ret = local;
01620 }
01621 else
01622 {
01623 if (local->data)
01624 {
01625 free(local->data);
01626 local->data = NULL;
01627 }
01628
01629 free(local);
01630 local = NULL;
01631 }
01632 }
01633 else
01634 {
01635 status = kDSDS_Stat_NoMemory;
01636 }
01637 }
01638 else
01639 {
01640 status = kDSDS_Stat_MissingAPI;
01641 }
01642 }
01643
01644 if (stat)
01645 {
01646 *stat = status;
01647 }
01648
01649 return ret;
01650 }
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665 long long DSDS_open_records(const char *dsspec,
01666 char *drmsSeries,
01667 DSDS_pHandle_t hparams,
01668 DSDS_KeyList_t ***keys,
01669 DRMS_Segment_t **segs,
01670 kDSDS_Stat_t *stat)
01671 {
01672 kDSDS_Stat_t status = kDSDS_Stat_Success;
01673 void *hSOI = GetSOI(&status);
01674 long long nRecs = 0;
01675 long long nDRMSRecs = 0;
01676 char drmsSeriesName[DRMS_MAXSERIESNAMELEN];
01677 KEY *params = NULL;
01678 char datafile[PATH_MAX];
01679 char datapath[PATH_MAX];
01680
01681 *drmsSeries = '\0';
01682 *keys = NULL;
01683 *segs = NULL;
01684 int keepsegs = 0;
01685
01686 if (hSOI)
01687 {
01688 pSOIFn_getkey_str_t pFn_getkey_str =
01689 (pSOIFn_getkey_str_t)GetSOIFPtr(hSOI, kSOI_GETKEY_STR);
01690 pSOIFn_getkey_int_t pFn_getkey_int =
01691 (pSOIFn_getkey_int_t)GetSOIFPtr(hSOI, kSOI_GETKEY_INT);
01692 pSOIFn_vds_last_record_t pFn_vds_last_record =
01693 (pSOIFn_vds_last_record_t)GetSOIFPtr(hSOI, kSOI_VDS_LAST_RECORD);
01694 pSOIFn_vds_open_t pFn_vds_open =
01695 (pSOIFn_vds_open_t)GetSOIFPtr(hSOI, kSOI_VDS_OPEN);
01696 pSOIFn_vds_close_t pFn_vds_close =
01697 (pSOIFn_vds_close_t)GetSOIFPtr(hSOI, kSOI_VDS_CLOSE);
01698 pSOIFn_VDS_select_hdr_t pFn_VDS_select_hdr =
01699 (pSOIFn_VDS_select_hdr_t)GetSOIFPtr(hSOI, kSOI_VDS_SELECT_HDR);
01700 pSOIFn_sds_datatype_t pFn_sds_datatype =
01701 (pSOIFn_sds_datatype_t)GetSOIFPtr(hSOI, kSOI_SDS_DATATYPE);
01702
01703 if (pFn_getkey_str &&
01704 pFn_getkey_int && pFn_vds_last_record && pFn_vds_open &&
01705 pFn_vds_close && pFn_VDS_select_hdr && pFn_sds_datatype)
01706 {
01707 VDS *vds = NULL;
01708 SDS *sds = NULL;
01709 int nds = 0;
01710 int ds = 0;
01711 char dsname[kDSDS_MaxKeyName];
01712 char key[kDSDS_MaxKeyName];
01713
01714 int fsn = 0;
01715 int lsn = 0;
01716 int sn = 0;
01717
01718 LinkedList_t *wdlist = NULL;
01719
01720 params = CreateSOIKeylist(dsspec, &wdlist, &status);
01721
01722 if (status == kDSDS_Stat_Success)
01723 {
01724 nds = (*pFn_getkey_int)(params, "in_nsets");
01725 nRecs = NumRecords(hSOI, nds, params, &status);
01726
01727 if (status == kDSDS_Stat_Success)
01728 {
01729
01730 if (keys && segs)
01731 {
01732
01733
01734
01735
01736
01737
01738
01739
01740 *keys = (DSDS_KeyList_t **)malloc(sizeof(DSDS_KeyList_t *) * nRecs);
01741 *segs = (DRMS_Segment_t *)malloc(sizeof(DRMS_Segment_t) * nRecs);
01742 if (*keys && *segs)
01743 {
01744 memset(*keys, 0, sizeof(DSDS_KeyList_t *) * nRecs);
01745 memset(*segs, 0, sizeof(DRMS_Segment_t) * nRecs);
01746 }
01747 else
01748 {
01749 status = kDSDS_Stat_NoMemory;
01750 }
01751 }
01752 else
01753 {
01754 status = kDSDS_Stat_InvalidParams;
01755 }
01756 }
01757 }
01758
01759
01760 int iRec = 0;
01761 for (ds = 0; status == kDSDS_Stat_Success && ds < nds; ds++)
01762 {
01763 sprintf(dsname, "in_%d", ds);
01764 if (ds == 0)
01765 {
01766
01767
01768
01769
01770
01771
01772 MakeDRMSSeriesName(hSOI,
01773 drmsSeriesName,
01774 sizeof(drmsSeriesName),
01775 params,
01776 dsname,
01777 &status);
01778 }
01779
01780 vds = (*pFn_vds_open)(params, dsname);
01781
01782 if (vds)
01783 {
01784 sprintf(key, "%s_fsn", dsname);
01785 fsn = (*pFn_getkey_int)(params, key);
01786 sprintf(key, "%s_lsn", dsname);
01787 lsn = (*pFn_getkey_int)(params, key);
01788
01789 if (lsn == -1)
01790 {
01791 lsn = (*pFn_vds_last_record)(vds);
01792 }
01793
01794
01795 snprintf(key, sizeof(key), "%s_series_sn", dsname);
01796 int series_num = (*pFn_getkey_int)(params, key);
01797
01798
01799 DRMS_Keyword_t *drmskey = NULL;
01800
01801 for (sn = fsn; status == kDSDS_Stat_Success && sn <= lsn; sn++)
01802 {
01803 DSDS_KeyList_t *pKL = NULL;
01804
01805 sds = (*pFn_VDS_select_hdr)(vds, 0, sn);
01806
01807 if (sds)
01808 {
01809
01810 (*keys)[nDRMSRecs] = (DSDS_KeyList_t *)malloc(sizeof(DSDS_KeyList_t));
01811 pKL = (*keys)[nDRMSRecs];
01812 pKL->next = NULL;
01813
01814 drmskey = (DRMS_Keyword_t *)malloc(sizeof(DRMS_Keyword_t));
01815 memset(drmskey, 0, sizeof(DRMS_Keyword_t));
01816 drmskey->info = (DRMS_KeywordInfo_t *)malloc(sizeof(DRMS_KeywordInfo_t));
01817 memset(drmskey->info, 0, sizeof(DRMS_KeywordInfo_t));
01818
01819 snprintf(drmskey->info->name, DRMS_MAXKEYNAMELEN, "%s", kDSDS_SERIES_NUM);
01820 drmskey->info->type = DRMS_TYPE_INT;
01821 GetKWFormat(drmskey->info->format, DRMS_MAXFORMATLEN, drmskey->info->type);
01822
01823 snprintf(drmskey->info->description,
01824 DRMS_MAXCOMMENTLEN,
01825 "%s",
01826 "Identifies dataset.");
01827
01828 (drmskey->value).int_val = series_num;
01829
01830 pKL->elem = drmskey;
01831
01832
01833 pKL->next = (DSDS_KeyList_t *)malloc(sizeof(DSDS_KeyList_t));
01834 pKL = pKL->next;
01835 pKL->next = NULL;
01836
01837 drmskey = (DRMS_Keyword_t *)malloc(sizeof(DRMS_Keyword_t));
01838 memset(drmskey, 0, sizeof(DRMS_Keyword_t));
01839 drmskey->info = (DRMS_KeywordInfo_t *)malloc(sizeof(DRMS_KeywordInfo_t));
01840 memset(drmskey->info, 0, sizeof(DRMS_KeywordInfo_t));
01841
01842 snprintf(drmskey->info->name, DRMS_MAXKEYNAMELEN, "%s", kDSDS_RN);
01843 drmskey->info->type = DRMS_TYPE_INT;
01844 GetKWFormat(drmskey->info->format, DRMS_MAXFORMATLEN, drmskey->info->type);
01845
01846 snprintf(drmskey->info->description,
01847 DRMS_MAXCOMMENTLEN,
01848 "%s",
01849 "Identifies record within dataset.");
01850
01851 (drmskey->value).int_val = sn;
01852
01853 pKL->elem = drmskey;
01854
01855
01856 pKL->next = (DSDS_KeyList_t *)malloc(sizeof(DSDS_KeyList_t));
01857 pKL = pKL->next;
01858 pKL->next = NULL;
01859
01860 drmskey = (DRMS_Keyword_t *)malloc(sizeof(DRMS_Keyword_t));
01861 memset(drmskey, 0, sizeof(DRMS_Keyword_t));
01862 drmskey->info = (DRMS_KeywordInfo_t *)malloc(sizeof(DRMS_KeywordInfo_t));
01863 memset(drmskey->info, 0, sizeof(DRMS_KeywordInfo_t));
01864
01865 snprintf(drmskey->info->name, DRMS_MAXKEYNAMELEN, "%s", kDSDS_DS);
01866 drmskey->info->type = DRMS_TYPE_INT;
01867 GetKWFormat(drmskey->info->format, DRMS_MAXFORMATLEN, drmskey->info->type);
01868
01869 snprintf(drmskey->info->description,
01870 DRMS_MAXCOMMENTLEN,
01871 "%s",
01872 "Identifies virtual dataset.");
01873
01874 (drmskey->value).int_val = ds;
01875
01876 pKL->elem = drmskey;
01877
01878
01879
01880 datafile[0] = '\0';
01881 int dataexist = 0;
01882 char *pdf = datafile;
01883 LoopAttrs(hSOI, sds, pKL, &status, &pdf, sizeof(datafile));
01884
01885 if (strlen(datafile) > 0)
01886 {
01887
01888
01889
01890
01891
01892
01893
01894 dataexist = 1;
01895 keepsegs = 1;
01896
01897 if (sds->filename && strlen(sds->filename) > 0)
01898 {
01899 snprintf(datapath, sizeof(datapath), "%s", sds->filename);
01900 }
01901 else if (vds->filename && strlen(vds->filename) > 0)
01902 {
01903 snprintf(datapath, sizeof(datapath), "%s", vds->filename);
01904 }
01905 else
01906 {
01907
01908 status = kDSDS_Stat_UnkFITSpath;
01909 }
01910 }
01911
01912
01913 DRMS_Segment_t *drmsseg = &((*segs)[nDRMSRecs]);
01914 kDSDS_Stat_t segstatus = kDSDS_Stat_Success;
01915
01916
01917
01918
01919
01920
01921 if (status == kDSDS_Stat_Success && dataexist)
01922 {
01923 FillDRMSSeg(hSOI,
01924 sds,
01925 drmsseg,
01926 kDSDS_Segment,
01927 DRMS_DSDS,
01928 datapath,
01929 &segstatus);
01930 }
01931
01932 if (segstatus != kDSDS_Stat_Success)
01933 {
01934
01935 FreeDSDSKeyList(&((*keys)[nDRMSRecs]));
01936 status = segstatus;
01937 }
01938
01939 if (status == kDSDS_Stat_Success)
01940 {
01941 nDRMSRecs++;
01942 }
01943 }
01944
01945 if (status == kDSDS_Stat_Success)
01946 {
01947 iRec++;
01948 }
01949 }
01950
01951 (*pFn_vds_close)(&vds);
01952 }
01953 }
01954
01955 list_llfree(&wdlist);
01956 }
01957 else
01958 {
01959 status = kDSDS_Stat_MissingAPI;
01960 }
01961 }
01962
01963 if (status == kDSDS_Stat_Success)
01964 {
01965 snprintf(drmsSeries, DRMS_MAXSERIESNAMELEN, "%s", drmsSeriesName);
01966 GenerateHandle("DSDS_KEY", params, hparams);
01967
01968 if (!keepsegs && segs)
01969 {
01970 DSDS_free_segarr(segs, nDRMSRecs);
01971 }
01972 }
01973 else
01974 {
01975 if (keys)
01976 {
01977 DSDS_free_keylistarr(keys, nDRMSRecs);
01978 }
01979 if (segs)
01980 {
01981 DSDS_free_segarr(segs, nDRMSRecs);
01982 }
01983 }
01984
01985 if (stat)
01986 {
01987 *stat = status;
01988 }
01989
01990 return nDRMSRecs;
01991 }
01992
01993 void DSDS_free_keylist(DSDS_KeyList_t **pkl)
01994 {
01995 if (pkl)
01996 {
01997 FreeDSDSKeyList(pkl);
01998 }
01999 }
02000
02001 void DSDS_free_keylistarr(DSDS_KeyList_t ***pklarr, int n)
02002 {
02003 int iRec;
02004
02005 if (pklarr)
02006 {
02007 DSDS_KeyList_t **arr = *pklarr;
02008
02009 if (arr)
02010 {
02011 for (iRec = 0; iRec < n; iRec++)
02012 {
02013 if (arr[iRec])
02014 {
02015 FreeDSDSKeyList(&(arr[iRec]));
02016 }
02017 }
02018
02019 free(arr);
02020 }
02021
02022 *pklarr = NULL;
02023 }
02024 }
02025
02026 void DSDS_free_seg(DRMS_Segment_t **seg)
02027 {
02028 if (seg && *seg)
02029 {
02030 if ((*seg)->info)
02031 {
02032 free((*seg)->info);
02033 }
02034
02035 free(*seg);
02036 *seg = NULL;
02037 }
02038 }
02039
02040
02041 void DSDS_free_segarr(DRMS_Segment_t **psarr, int n)
02042 {
02043 if (psarr && *psarr)
02044 {
02045 int i;
02046 for (i = 0; i < n; i++)
02047 {
02048 DRMS_Segment_t *seg = (*psarr + i);
02049
02050
02051 if (seg->info)
02052 {
02053 free(seg->info);
02054 }
02055 }
02056
02057 free(*psarr);
02058 }
02059
02060 *psarr = NULL;
02061 }
02062
02063 void DSDS_steal_seginfo(DRMS_Segment_t *thief, DRMS_Segment_t *victim)
02064 {
02065
02066 if (thief && victim)
02067 {
02068 *thief = *victim;
02069 victim->info = NULL;
02070 victim->record = NULL;
02071 }
02072 }
02073
02074
02075
02076
02077
02078 void DSDS_free_vdscache()
02079 {
02080 destroyVDSCache();
02081 }
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092 DRMS_Array_t *DSDS_segment_read(char *paramsDesc, int ds, int rn, const char *filename, kDSDS_Stat_t *stat)
02093 {
02094 kDSDS_Stat_t status = kDSDS_Stat_Success;
02095 void *hSOI = GetSOI(&status);
02096 DRMS_Array_t *ret = NULL;
02097 DRMS_Array_t *local = NULL;
02098
02099 if (hSOI)
02100 {
02101 if (!paramsDesc)
02102 {
02103 pSOIFn_sds_read_fits_t pFn_sds_read_fits =
02104 (pSOIFn_sds_read_fits_t)GetSOIFPtr(hSOI, kSOI_SDS_READ_FITS);
02105 pSOIFn_sds_free_t pFn_sds_free =
02106 (pSOIFn_sds_free_t)GetSOIFPtr(hSOI, kSOI_SDS_FREE);
02107
02108 if (pFn_sds_read_fits && pFn_sds_free)
02109 {
02110 FILE *fp = fopen(filename, "r");
02111 if (fp)
02112 {
02113 SDS *sds = (*pFn_sds_read_fits)(fp);
02114 if (sds)
02115 {
02116 fclose(fp);
02117 fp = NULL;
02118 local = CreateDRMSArray(hSOI, sds, &status);
02119 (*pFn_sds_free)(&sds);
02120 }
02121 }
02122 }
02123 else
02124 {
02125 status = kDSDS_Stat_MissingAPI;
02126 }
02127 }
02128 else
02129 {
02130 pSOIFn_vds_open_t pFn_vds_open =
02131 (pSOIFn_vds_open_t)GetSOIFPtr(hSOI, kSOI_VDS_OPEN);
02132 pSOIFn_VDS_select_rec_t pFn_VDS_select_rec =
02133 (pSOIFn_VDS_select_rec_t)GetSOIFPtr(hSOI, kSOI_VDS_SELECT_REC);
02134 pSOIFn_vds_close_t pFn_vds_close =
02135 (pSOIFn_vds_close_t)GetSOIFPtr(hSOI, kSOI_VDS_CLOSE);
02136 pSOIFn_sds_free_data_t pFn_sds_free_data =
02137 (pSOIFn_sds_free_data_t)GetSOIFPtr(hSOI, kSOI_SDS_FREE_DATA);
02138
02139
02140
02141
02142
02143
02144
02145 SDS *sds = NULL;
02146 VDS *vds = NULL;
02147 KEY *keylist = NULL;
02148 char dsname[kDSDS_MaxKeyName];
02149
02150 if (pFn_vds_open && pFn_VDS_select_rec && pFn_vds_close && pFn_sds_free_data)
02151 {
02152 DSDS_Handle_t hparams = FindHandle(paramsDesc);
02153 GetStructure(hparams, (void **)&keylist);
02154 sprintf(dsname, "in_%d", ds);
02155 vds = getVDS(keylist, dsname, hparams, NULL);
02156
02157 if (vds)
02158 {
02159 sds = (*pFn_VDS_select_rec)(vds, 0, rn);
02160
02161 if (sds)
02162 {
02163 local = CreateDRMSArray(hSOI, sds, &status);
02164
02165
02166
02167
02168 (*pFn_sds_free_data)(sds);
02169 }
02170
02171
02172 }
02173 }
02174 else
02175 {
02176 status = kDSDS_Stat_MissingAPI;
02177 }
02178 }
02179 }
02180
02181 if (status == kDSDS_Stat_Success)
02182 {
02183 ret = local;
02184 }
02185
02186 if (stat)
02187 {
02188 *stat = status;
02189 }
02190
02191 return ret;
02192 }
02193
02194 void DSDS_free_array(DRMS_Array_t **arr)
02195 {
02196 if (arr && *arr)
02197 {
02198 if ((*arr)->data)
02199 {
02200 free((*arr)->data);
02201 }
02202
02203 free(*arr);
02204 *arr = NULL;
02205 }
02206 }
02207
02208 void DSDS_handle_todesc(DSDS_Handle_t handle, char *desc, kDSDS_Stat_t *stat)
02209 {
02210 int error = 1;
02211
02212
02213 if (handle)
02214 {
02215 if (FindHandle(handle))
02216 {
02217 error = 0;
02218 snprintf(desc, kDSDS_MaxHandle, "[%s]", handle);
02219 }
02220 }
02221
02222 if (stat)
02223 {
02224 if (error)
02225 {
02226 *stat = kDSDS_Stat_InvalidHandle;
02227 }
02228 else
02229 {
02230 *stat = kDSDS_Stat_Success;
02231 }
02232 }
02233 }
02234
02235 void DSDS_free_handle(DSDS_pHandle_t pHandle)
02236 {
02237
02238 removeVDSFromCache(*pHandle);
02239
02240 DestroyHandle(pHandle);
02241 }
02242
02243
02244 int DSDS_read_fitsheader(const char *file,
02245 DSDS_KeyList_t **keylist,
02246 DRMS_Segment_t **seg,
02247 const char *segname,
02248 kDSDS_Stat_t *stat)
02249 {
02250 kDSDS_Stat_t status = kDSDS_Stat_InvalidFITS;
02251 DSDS_KeyList_t *retlist = NULL;
02252 DRMS_Segment_t *retseg = NULL;
02253 int nKeys = 0;
02254
02255 void *hSOI = GetSOI(&status);
02256
02257 if (hSOI)
02258 {
02259 pSOIFn_sds_get_fits_head_t pFn_sds_get_fits_head =
02260 (pSOIFn_sds_get_fits_head_t)GetSOIFPtr(hSOI, kSOI_SDS_GET_FITS_HEAD);
02261 pSOIFn_sds_free_t pFn_sds_free =
02262 (pSOIFn_sds_free_t)GetSOIFPtr(hSOI, kSOI_SDS_FREE);
02263
02264 if (pFn_sds_get_fits_head && pFn_sds_free)
02265 {
02266 char *fitsfile = strdup(file);
02267 SDS *sds = (*pFn_sds_get_fits_head)(fitsfile);
02268 if (sds)
02269 {
02270
02271 retlist = (DSDS_KeyList_t *)malloc(sizeof(DSDS_KeyList_t));
02272 if (retlist)
02273 {
02274 retlist->elem = NULL;
02275 retlist->next = NULL;
02276
02277
02278 nKeys = LoopAttrs(hSOI, sds, retlist, &status, NULL, 0);
02279 }
02280 else
02281 {
02282 status = kDSDS_Stat_NoMemory;
02283 }
02284
02285 retseg = (DRMS_Segment_t *)malloc(sizeof(DRMS_Segment_t));
02286 memset(retseg, 0, sizeof(DRMS_Segment_t));
02287 if (retseg)
02288 {
02289 FillDRMSSeg(hSOI, sds, retseg, segname, DRMS_LOCAL, fitsfile, &status);
02290 }
02291 else
02292 {
02293 status = kDSDS_Stat_NoMemory;
02294 }
02295
02296 (*pFn_sds_free)(&sds);
02297 }
02298
02299 if (fitsfile)
02300 {
02301 free(fitsfile);
02302 }
02303 }
02304 else
02305 {
02306 status = kDSDS_Stat_MissingAPI;
02307 }
02308 }
02309
02310 if (stat)
02311 {
02312 *stat = status;
02313 }
02314
02315 if (status == kDSDS_Stat_Success)
02316 {
02317 if (keylist)
02318 {
02319 *keylist = retlist;
02320 }
02321 if (seg)
02322 {
02323 *seg = retseg;
02324 }
02325 }
02326 else
02327 {
02328 if (retlist)
02329 {
02330 free(retlist);
02331 }
02332 if (retseg)
02333 {
02334 free(retseg);
02335 }
02336 }
02337
02338 return nKeys;
02339 }