00001
00002
00081 #include <sys/types.h>
00082 #include <pwd.h>
00083 #include "jsoc_main.h"
00084
00085 char *module_name = "set_suretention";
00086
00087 typedef enum
00088 {
00089 kSetRetStatus_Success = 0,
00090 kSetRetStatus_OutOfMemory,
00091 kSetRetStatus_ChunkFetch,
00092 kSetRetStatus_SumGet,
00093 kSetRetStatus_Spec,
00094 kSetRetStatus_CleanUp,
00095 kSetRetStatus_Argument,
00096 kSetRetStatus_FileIO,
00097 kSetRetStatus_TimeOut
00098 } SetRetStatus_t;
00099
00100 #define SULIST "sulist"
00101 #define NEWRETENTION "retention"
00102 #define NRECS "n"
00103 #define AUTOBANG "b"
00104 #define DISABLETO "O"
00105 #define kNotSpec "NOTSPECIFIED"
00106
00107 ModuleArgs_t module_args[] =
00108 {
00109 {ARG_STRING, SULIST, NULL, "a list of SUNUMs, or a file containing a list of SUNUMS, or a DRMS record-set specification resolving to a list of SUNUMs", NULL},
00110 {ARG_INT, NEWRETENTION, NULL, "the new retention value to which all SUs will be set"},
00111 {ARG_INT, NRECS, "0", "the number of records to accept - a positive number denotes the number of head records, a negative number denotes the number of tail records"},
00112 {ARG_FLAG, AUTOBANG, NULL, "disable prime-key logic"},
00113 {ARG_FLAG, DISABLETO, NULL, "disable the code that sets a database query time-out of 10 minutes"},
00114 {ARG_END}
00115 };
00116
00117 #define FILE_CHUNK_SIZE -1
00118
00119 struct SUSR_Spec_struct
00120 {
00121 int maxHeadRecs;
00122 int maxTailRecs;
00123 char *spec;
00124 };
00125
00126 typedef struct SUSR_Spec_struct SUSR_Spec_t;
00127
00128 struct SUSR_List_struct
00129 {
00130 int num;
00131 long long *arr;
00132 };
00133
00134 typedef struct SUSR_List_struct SUSR_List_t;
00135
00136 struct SUSR_Cache_struct
00137 {
00138 HContainer_t *map;
00139 HIterator_t *hit;
00140 };
00141
00142 typedef struct SUSR_Cache_struct SUSR_Cache_t;
00143
00144
00145
00146
00147
00148
00149
00150 typedef long long *(*pFnFetchChunk_t)(DRMS_Env_t *, void *, int *, int);
00151
00152
00153 static long long readSUNUMFromFile(FILE *fp, int *status)
00154 {
00155 char oneChar;
00156 int count;
00157 char sunum[64];
00158 long long rv;
00159 int istat;
00160
00161 for (count = 0, *sunum = '\0', istat = 0; (oneChar = (char)fgetc(fp)) != EOF;)
00162 {
00163
00164 if (oneChar == ' ' || oneChar == '\t')
00165 {
00166 continue;
00167 }
00168
00169 if (oneChar == '\n' && count == 0)
00170 {
00171
00172 continue;
00173 }
00174
00175
00176 if (oneChar == '\n')
00177 {
00178
00179 break;
00180 }
00181 else
00182 {
00183
00184 if (count < sizeof(sunum) - 1)
00185 {
00186 sunum[count++] = oneChar;
00187 }
00188 else
00189 {
00190 istat = 1;
00191 sunum[count] = '\0';
00192 fprintf(stderr, "Too many chars in SUNUM: %s.\n", sunum);
00193 break;
00194 }
00195 }
00196 }
00197
00198 sunum[count] = '\0';
00199
00200 if (count > 0)
00201 {
00202 char *endptr = NULL;
00203
00204 rv = strtoll(sunum, &endptr, 0);
00205
00206 if (rv == 0 && endptr == sunum)
00207 {
00208
00209 istat = 1;
00210 fprintf(stderr, "Not a valid SUNUM: %s.\n", sunum);
00211 }
00212 }
00213 else
00214 {
00215 rv = -1;
00216 }
00217
00218 if (status)
00219 {
00220 *status = istat;
00221 }
00222
00223 return rv;
00224 }
00225
00226 static int isAFile(const char *spec)
00227 {
00228 struct stat stBuf;
00229
00230 if (!stat(spec, &stBuf))
00231 {
00232 if (S_ISREG(stBuf.st_mode) || S_ISLNK(stBuf.st_mode))
00233 {
00234 return 1;
00235 }
00236 }
00237
00238 return 0;
00239 }
00240
00241 static long long *gimmeAChunk(DRMS_Env_t *env, pFnFetchChunk_t fxn, void *data, int *chunkSize, SetRetStatus_t *status)
00242 {
00243 long long *chunk = NULL;
00244 SetRetStatus_t istat;
00245
00246 istat = kSetRetStatus_Success;
00247 chunk = fxn(env, data, chunkSize, 0);
00248
00249 if (chunk == (long long *)-1LL)
00250 {
00251
00252 istat = kSetRetStatus_ChunkFetch;
00253 }
00254
00255 if (status)
00256 {
00257 *status = istat;
00258 }
00259
00260 return chunk;
00261 }
00262
00263 static void freeAChunk(long long **chunk)
00264 {
00265 if (chunk && *chunk)
00266 {
00267 free(*chunk);
00268 *chunk = NULL;
00269 }
00270 }
00271
00272
00273 static int processChunk(DRMS_Env_t *env, int16_t newRetention, int nsus, long long *sunums)
00274 {
00275 if (nsus > 0 && sunums)
00276 {
00277 return (drms_setretention(env, newRetention, nsus, sunums) != DRMS_SUCCESS);
00278 }
00279 else
00280 {
00281 return 0;
00282 }
00283 }
00284
00285 static SetRetStatus_t callSumGet(DRMS_Env_t *env, pFnFetchChunk_t fxn, void *data, int chunkSize, int16_t newRetention)
00286 {
00287 long long *sunums;
00288 int chunkSizeRet;
00289 SetRetStatus_t istat;
00290 int totalN;
00291
00292 sunums = NULL;
00293 chunkSizeRet = chunkSize;
00294 totalN = 0;
00295 istat = kSetRetStatus_Success;
00296
00297 while ((sunums = gimmeAChunk(env, fxn, data, &chunkSizeRet, &istat)) && istat == kSetRetStatus_Success)
00298 {
00299 totalN += chunkSizeRet;
00300
00301
00302 if (processChunk(env, newRetention, chunkSizeRet, sunums))
00303 {
00304 istat = kSetRetStatus_SumGet;
00305 }
00306
00307 if (sunums)
00308 {
00309 freeAChunk(&sunums);
00310 }
00311 }
00312
00313 if (istat == kSetRetStatus_Success)
00314 {
00315 chunkSizeRet = -1;
00316 if (NULL != (*fxn)(env, NULL, &chunkSizeRet, 1))
00317 {
00318
00319 istat = kSetRetStatus_CleanUp;
00320 }
00321 }
00322
00323 if (totalN == 0)
00324 {
00325 fprintf(stderr, "WARNING: sulist did not specify any storage units whose retention could be modified.\n");
00326 }
00327
00328 return istat;
00329 }
00330
00331 static int sunumSort(const void *he1, const void *he2)
00332 {
00333 long long *ps1 = (long long *)hcon_getval(*((HContainerElement_t **)he1));
00334 long long *ps2 = (long long *)hcon_getval(*((HContainerElement_t **)he2));
00335
00336 XASSERT(ps1 && ps2);
00337
00338 long long s1 = *ps1;
00339 long long s2 = *ps2;
00340
00341 return (s1 < s2) ? -1 : (s1 > s2 ? 1 : 0);
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 static long long getNextOwnedSunum(DRMS_Env_t *env, SUSR_Cache_t **cache, long long *data, int num)
00353 {
00354 long long rv = -1;
00355 int drmsStatus;
00356
00357 drmsStatus = DRMS_SUCCESS;
00358
00359 if (cache)
00360 {
00361 if (!*cache)
00362 {
00363 *cache = calloc(1, sizeof(SUSR_Cache_t));
00364
00365 if (!cache)
00366 {
00367 fprintf(stderr, "Out of memory.\n");
00368 }
00369 else
00370 {
00371 (*cache)->map = hcon_create(sizeof(long long), 64, NULL, NULL, NULL, NULL, 0);
00372 if (!(*cache)->map)
00373 {
00374 fprintf(stderr, "Out of memory.\n");
00375 }
00376 }
00377 }
00378
00379
00380 if (data)
00381 {
00382 if (*cache && (*cache)->map)
00383 {
00384 SUM_info_t **info = NULL;
00385 int isunum;
00386 const char *series = NULL;
00387 long long sunum;
00388 DRMS_Record_t *template = NULL;
00389 char sunumStr[64];
00390
00391 info = (SUM_info_t **)calloc(num, sizeof(SUM_info_t *));
00392 if (info)
00393 {
00394 drmsStatus = drms_getsuinfo(env, data, num, info);
00395
00396
00397 if (drmsStatus != DRMS_SUCCESS)
00398 {
00399 fprintf(stderr, "Error fetching SUMS info.\n");
00400 }
00401 else
00402 {
00403 rv = 0;
00404
00405 for (isunum = 0; isunum < num; isunum++)
00406 {
00407 if (*info[isunum]->online_loc == '\0')
00408 {
00409
00410 fprintf(stderr, "WARNING: Invalid sunum: %llu.\n", (unsigned long long)info[isunum]->sunum);
00411
00412 continue;
00413 }
00414
00415 sunum = info[isunum]->sunum;
00416 series = info[isunum]->owning_series;
00417 template = drms_template_record(env, series, &drmsStatus);
00418
00419 if (!template)
00420 {
00421 fprintf(stderr, "Unknown series %s for SUNUM %lld, skipping.\n", series, sunum);
00422 continue;
00423 }
00424
00425 snprintf(sunumStr, sizeof(sunumStr), "%lld", sunum);
00426
00427 if (!hcon_member((*cache)->map, sunumStr))
00428 {
00429 if (template->seriesinfo && template->seriesinfo->retention_perm)
00430 {
00431 hcon_insert((*cache)->map, sunumStr, &sunum);
00432 }
00433 else
00434 {
00435 fprintf(stderr, "WARNING: You do not have permission to modify the retention on SUNUM %s in series %s.\n", sunumStr, template->seriesinfo && *template->seriesinfo->seriesname != '\0' ? template->seriesinfo->seriesname : "<unknown>");
00436 }
00437 }
00438 }
00439 }
00440
00441 for (isunum = 0; isunum < num; isunum++)
00442 {
00443 if (info[isunum])
00444 {
00445 free(info[isunum]);
00446 info[isunum] = NULL;
00447 }
00448 }
00449
00450 free(info);
00451 info = NULL;
00452 }
00453 else
00454 {
00455 fprintf(stderr, "Out of memory.\n");
00456 }
00457 }
00458 }
00459 else
00460 {
00461
00462 if (*cache && (*cache)->map)
00463 {
00464 long long *pOneSunum = NULL;
00465
00466 if (!(*cache)->hit)
00467 {
00468 (*cache)->hit = calloc(1, sizeof(HIterator_t));
00469
00470 if (!(*cache)->hit)
00471 {
00472 fprintf(stderr, "Out of memory.\n");
00473 }
00474 else
00475 {
00476 hiter_new_sort((*cache)->hit, (*cache)->map, sunumSort);
00477 }
00478 }
00479
00480 if ((*cache)->hit)
00481 {
00482 if ((pOneSunum = (long long *)hiter_getnext((*cache)->hit)) != NULL)
00483 {
00484 rv = *pOneSunum;
00485 }
00486 else
00487 {
00488
00489 rv = -2;
00490 }
00491 }
00492 }
00493 }
00494 }
00495
00496 return rv;
00497 }
00498
00499
00500
00501
00502
00503 static long long *getChunkFromFile(DRMS_Env_t *env, void *data, int *chunkSize, int clean)
00504 {
00505 static SUSR_Cache_t *infoCache = NULL;
00506
00507 long long sunum;
00508 int count;
00509 int istat;
00510 long long *rv = NULL;
00511 long long *arr = NULL;
00512 int nSunums;
00513
00514 count = 0;
00515 istat = 0;
00516
00517 if (clean)
00518 {
00519 if (infoCache)
00520 {
00521 hiter_destroy(&infoCache->hit);
00522 hcon_destroy(&infoCache->map);
00523 free(infoCache);
00524 infoCache = NULL;
00525 }
00526 }
00527 else
00528 {
00529
00530 if (data && !infoCache)
00531 {
00532 const char *fileName = NULL;
00533 FILE *fptr = NULL;
00534
00535 fileName = (const char *)data;
00536 fptr = fopen(fileName, "r");
00537 if (!fptr)
00538 {
00539 fprintf(stderr, "Unable to open file %s for reading.\n", fileName);
00540 istat = 1;
00541 }
00542 else
00543 {
00544 LinkedList_t *list = NULL;
00545 ListNode_t *node = NULL;
00546 int isunum;
00547
00548 list = list_llcreate(sizeof(long long), NULL);
00549
00550
00551
00552 if (list)
00553 {
00554
00555 nSunums = 0;
00556 while ((sunum = readSUNUMFromFile(fptr, &istat)) != -1)
00557 {
00558 list_llinserttail(list, &sunum);
00559 nSunums++;
00560 }
00561
00562 if (!istat)
00563 {
00564 nSunums = list->nitems;
00565 arr = calloc(sizeof(long long), nSunums);
00566
00567 if (arr)
00568 {
00569 list_llreset(list);
00570 isunum = 0;
00571 while ((node = list_llnext(list)) != NULL)
00572 {
00573 arr[isunum] = *((long long *)node->data);
00574 isunum++;
00575 }
00576
00577
00578 if (getNextOwnedSunum(env, &infoCache, arr, nSunums) == -1)
00579 {
00580
00581 istat = 1;
00582 }
00583
00584 free(arr);
00585 arr = NULL;
00586 }
00587 else
00588 {
00589 istat = 1;
00590 fprintf(stderr, "Out of memory.\n");
00591 }
00592 }
00593
00594 list_llfree(&list);
00595 }
00596 else
00597 {
00598 istat = 1;
00599 fprintf(stderr, "Out of memory.\n");
00600 }
00601 }
00602 }
00603
00604 if (!istat && infoCache)
00605 {
00606 nSunums = (*chunkSize == -1) ? hcon_size(infoCache->map) : *chunkSize;
00607 rv = calloc(sizeof(long long), nSunums);
00608
00609 if (!rv)
00610 {
00611 istat = 1;
00612 fprintf(stderr, "Out of memory.\n");
00613 }
00614
00615 if (!istat)
00616 {
00617 while ((*chunkSize == -1 || count < *chunkSize) && ((sunum = getNextOwnedSunum(env, &infoCache, NULL, -1)) >= 0))
00618 {
00619 rv[count] = sunum;
00620 count++;
00621 }
00622
00623 if (sunum == -1)
00624 {
00625
00626 istat = 1;
00627 }
00628 else if (sunum == -2)
00629 {
00630
00631 }
00632 }
00633 }
00634 }
00635
00636 if (istat)
00637 {
00638 rv = (long long *)-1LL;
00639 }
00640
00641 if (!clean && count == 0 && rv && rv != (long long *)-1LL)
00642 {
00643
00644 free(rv);
00645 rv = NULL;
00646 }
00647
00648 *chunkSize = count;
00649
00650 return rv;
00651 }
00652
00653
00654
00655
00656
00657
00658
00659 static long long *getChunkFromList(DRMS_Env_t *env, void *data, int *chunkSize, int clean)
00660 {
00661 static SUSR_Cache_t *infoCache = NULL;
00662 int count;
00663 int istat;
00664 long long *rv = NULL;
00665
00666 count = 0;
00667 istat = 0;
00668
00669 if (clean)
00670 {
00671 if (infoCache)
00672 {
00673 hiter_destroy(&infoCache->hit);
00674 hcon_destroy(&infoCache->map);
00675 free(infoCache);
00676 infoCache = NULL;
00677 }
00678 }
00679 else
00680 {
00681 if (data && !infoCache)
00682 {
00683 SUSR_List_t *list = NULL;
00684
00685 list = (SUSR_List_t *)data;
00686
00687
00688 if (getNextOwnedSunum(env, &infoCache, list->arr, list->num) == -1)
00689 {
00690
00691 istat = 1;
00692 }
00693 }
00694
00695 if (!istat && infoCache)
00696 {
00697 int nSunums;
00698
00699 nSunums = (*chunkSize == -1) ? hcon_size(infoCache->map) : *chunkSize;
00700 rv = calloc(sizeof(long long), nSunums);
00701
00702 if (!rv)
00703 {
00704 fprintf(stderr, "Out of memory.\n");
00705 istat = 1;
00706 }
00707
00708 if (!istat)
00709 {
00710 long long sunum;
00711
00712 while ((*chunkSize == -1 || count < *chunkSize) && ((sunum = getNextOwnedSunum(env, &infoCache, NULL, -1)) >= 0))
00713 {
00714 rv[count] = sunum;
00715 count++;
00716 }
00717
00718 if (sunum == -1)
00719 {
00720
00721 istat = 1;
00722 }
00723 else if (sunum == -2)
00724 {
00725
00726 }
00727 }
00728 }
00729 }
00730
00731 if (istat)
00732 {
00733 rv = (long long *)-1LL;
00734 }
00735
00736 if (!clean && count == 0 && rv && rv != (long long *)-1LL)
00737 {
00738
00739 free(rv);
00740 rv = NULL;
00741 }
00742
00743 *chunkSize = count;
00744
00745 return rv;
00746 }
00747
00748
00749
00750
00751
00752
00753
00754 static long long *getChunkFromSpec(DRMS_Env_t *env, void *data, int *chunkSize, int clean)
00755 {
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 static DRMS_RecordSet_t *recordset = NULL;
00769 static SUSR_Cache_t *infoCache = NULL;
00770
00771 long long *rv = NULL;
00772 int count;
00773 int nRecs;
00774 int drmsStatus;
00775 int istat;
00776
00777 count = 0;
00778 drmsStatus = DRMS_SUCCESS;
00779 istat = 0;
00780
00781 if (clean)
00782 {
00783 if (infoCache)
00784 {
00785 hiter_destroy(&infoCache->hit);
00786 hcon_destroy(&infoCache->map);
00787 free(infoCache);
00788 infoCache = NULL;
00789 }
00790
00791 if (recordset)
00792 {
00793 drms_close_records(recordset, DRMS_FREE_RECORD);
00794 recordset = NULL;
00795 }
00796 }
00797 else
00798 {
00799 if (data && !recordset && !infoCache)
00800 {
00801 SUSR_Spec_t *specData = NULL;
00802 int maxHeadRecs;
00803 int maxTailRecs;
00804 const char *spec = NULL;
00805
00806
00807 specData = (SUSR_Spec_t *)data;
00808
00809 maxHeadRecs = specData->maxHeadRecs;
00810 maxTailRecs = specData->maxTailRecs;
00811 spec = specData->spec;
00812
00813 if (maxHeadRecs >= 0)
00814 {
00815 recordset = drms_open_nrecords(env, spec, maxHeadRecs, &drmsStatus);
00816 if (recordset)
00817 {
00818 nRecs = recordset->n;
00819 }
00820 }
00821 else if (maxTailRecs >= 0)
00822 {
00823 recordset = drms_open_nrecords(env, spec, -1 * maxTailRecs, &drmsStatus);
00824 if (recordset)
00825 {
00826 nRecs = recordset->n;
00827 }
00828 }
00829 else
00830 {
00831 DRMS_Array_t *array = NULL;
00832
00833
00834 array = drms_record_getvector(env, spec, "sunum", DRMS_TYPE_LONGLONG, 0, &drmsStatus);
00835
00836 if (array && drmsStatus == DRMS_SUCCESS)
00837 {
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850 HContainer_t *uniqueMap = NULL;
00851 long long *unique = NULL;
00852 int isunum;
00853 char sunumStr[64];
00854 int countUnique;
00855 char dummy;
00856
00857
00858 nRecs = drms_array_count(array);
00859 uniqueMap = hcon_create(sizeof(char), 64, NULL, NULL, NULL, NULL, 0);
00860 unique = calloc(nRecs, sizeof(long long));
00861
00862 if (!uniqueMap || !unique)
00863 {
00864 fprintf(stderr, "Out of memory.\n");
00865 istat = 1;
00866 }
00867 else
00868 {
00869 for (isunum = 0, countUnique = 0, dummy = 'y'; isunum < nRecs; isunum++)
00870 {
00871 snprintf(sunumStr, sizeof(sunumStr), "%lld", ((long long *)array->data)[isunum]);
00872
00873 if (!hcon_member(uniqueMap, sunumStr))
00874 {
00875 unique[countUnique] = ((long long *)array->data)[isunum];
00876 countUnique++;
00877 hcon_insert(uniqueMap, sunumStr, &dummy);
00878 }
00879 }
00880
00881
00882 if (getNextOwnedSunum(env, &infoCache, unique, countUnique) == -1)
00883 {
00884
00885 istat = 1;
00886 }
00887
00888 free(unique);
00889 unique = NULL;
00890 hcon_destroy(&uniqueMap);
00891 }
00892 }
00893
00894 if (array)
00895 {
00896 drms_free_array(array);
00897 array = NULL;
00898 }
00899 }
00900
00901 if (drmsStatus != DRMS_SUCCESS)
00902 {
00903 fprintf(stderr, "Error retrieving DRMS records from the database.\n");
00904
00905 if (drmsStatus == DRMS_ERROR_QUERYFAILED)
00906 {
00907
00908 const char *emsg = DB_GetErrmsg(env->session->db_handle);
00909
00910 if (emsg)
00911 {
00912 fprintf(stderr, "DB error message: %s\n", emsg);
00913 }
00914 }
00915
00916 istat = 1;
00917 }
00918 }
00919
00920 if (!istat && (recordset || infoCache))
00921 {
00922 int nSunums;
00923
00924 if (*chunkSize != -1)
00925 {
00926 nSunums = *chunkSize;
00927 }
00928 else
00929 {
00930 nSunums = recordset ? recordset->n : hcon_size(infoCache->map);
00931 }
00932
00933 rv = calloc(sizeof(long long), nSunums);
00934
00935 if (!rv)
00936 {
00937 fprintf(stderr, "Out of memory.\n");
00938 istat = 1;
00939 }
00940
00941 if (!istat)
00942 {
00943
00944 if (recordset)
00945 {
00946 DRMS_Record_t *rec = NULL;
00947 DRMS_RecChunking_t cstat = kRecChunking_None;
00948 int newchunk;
00949
00950 while ((*chunkSize == -1 || count < *chunkSize) && (rec = drms_recordset_fetchnext(env, recordset, &drmsStatus, &cstat, &newchunk)) != NULL && drmsStatus == 0)
00951 {
00952
00953
00954 if (rec->sunum >= 0 && rec->seriesinfo && rec->seriesinfo->retention_perm)
00955 {
00956 rv[count] = rec->sunum;
00957 count++;
00958 }
00959 }
00960
00961 if (drmsStatus != DRMS_SUCCESS)
00962 {
00963 istat = 1;
00964 }
00965 }
00966 else if (infoCache)
00967 {
00968 long long sunum;
00969
00970 while ((*chunkSize == -1 || count < *chunkSize) && ((sunum = getNextOwnedSunum(env, &infoCache, NULL, -1)) >= 0))
00971 {
00972 rv[count] = sunum;
00973 count++;
00974 }
00975
00976 if (sunum == -1)
00977 {
00978
00979 istat = 1;
00980 }
00981 else if (sunum == -2)
00982 {
00983
00984 }
00985 }
00986 }
00987 else
00988 {
00989 fprintf(stderr, "Out of memory.\n");
00990 }
00991 }
00992 }
00993
00994 if (istat)
00995 {
00996 rv = (long long *)-1LL;
00997 }
00998
00999 if (!clean && count == 0 && rv && rv != (long long *)-1LL)
01000 {
01001
01002 free(rv);
01003 rv = NULL;
01004 }
01005
01006 *chunkSize = count;
01007
01008 return rv;
01009 }
01010
01011 char *insertAutoBang(DRMS_Env_t *env, const char *spec, const char *autobangStr, char **sets, DRMS_RecordSetType_t *settypes, char **snames, int nsets, int *status)
01012 {
01013 int drmsStatus;
01014 DRMS_Record_t *templRec = NULL;
01015 char *filter = NULL;
01016 char *filterbuf = NULL;
01017 size_t fbsz = 128;
01018 char *intermed = NULL;
01019 char *rv = NULL;
01020 int iset;
01021 int istat;
01022
01023 filterbuf = calloc(fbsz, sizeof(char));
01024 rv = strdup(spec);
01025 istat = 0;
01026
01027 if (!filterbuf || !rv)
01028 {
01029 fprintf(stderr, "Out of memory.\n");
01030 istat = 1;
01031 }
01032 else
01033 {
01034 for (iset = 0; iset < nsets && !istat; iset++)
01035 {
01036 if (settypes[iset] == kRecordSetType_DSDSPort || settypes[iset] == kRecordSetType_DRMS)
01037 {
01038 templRec = drms_template_record(env, snames[iset], &drmsStatus);
01039 if (DRMS_ERROR_UNKNOWNSERIES == drmsStatus)
01040 {
01041 fprintf(stderr, "Unable to open template record for series '%s'; this series does not exist.\n", snames[iset]);
01042 istat = 1;
01043 }
01044 else
01045 {
01046 filter = drms_recordset_extractfilter(templRec, sets[iset], &istat);
01047
01048 if (!istat)
01049 {
01050 *filterbuf = '\0';
01051 if (filter)
01052 {
01053 filterbuf = base_strcatalloc(filterbuf, filter, &fbsz);
01054 filterbuf = base_strcatalloc(filterbuf, autobangStr, &fbsz);
01055
01056
01057 intermed = base_strreplace(rv, filter, filterbuf);
01058 free(rv);
01059 rv = intermed;
01060 }
01061 else
01062 {
01063 filterbuf = base_strcatalloc(filterbuf, snames[iset], &fbsz);
01064 filterbuf = base_strcatalloc(filterbuf, autobangStr, &fbsz);
01065
01066
01067 intermed = base_strreplace(rv, snames[iset], filterbuf);
01068 free(rv);
01069 rv = intermed;
01070 }
01071 }
01072
01073 if (filter)
01074 {
01075 free(filter);
01076 filter = NULL;
01077 }
01078 }
01079 }
01080 }
01081
01082 if (istat)
01083 {
01084 if (rv)
01085 {
01086 free(rv);
01087 rv = NULL;
01088 }
01089 }
01090
01091 free(filterbuf);
01092 filterbuf = NULL;
01093 }
01094
01095 if (status)
01096 {
01097 *status = istat;
01098 }
01099
01100 return rv;
01101 }
01102
01103
01104
01105
01106
01107
01108 int DoIt(void)
01109 {
01110 SetRetStatus_t rv = kSetRetStatus_Success;
01111 int cpStat;
01112 const char *autobangStr = NULL;
01113 int disableTO;
01114 const char *sulist = NULL;
01115 int16_t newRetention;
01116 int maxHeadRecs;
01117 int maxTailRecs;
01118 int nRecs;
01119
01120
01121
01122 drms_env->retention = INT16_MIN;
01123
01124 sulist = cmdparams_get_str(&cmdparams, SULIST, NULL);
01125 newRetention = cmdparams_get_int16(&cmdparams, NEWRETENTION, &cpStat);
01126 if (cpStat == CMDPARAMS_INVALID_CONVERSION)
01127 {
01128
01129 if (newRetention < 0)
01130 {
01131 fprintf(stderr, "The retention-argument value must be a positive 15-bit number.\n");
01132 rv = kSetRetStatus_Argument;
01133 }
01134 }
01135
01136 if (rv == kSetRetStatus_Success)
01137 {
01138 maxHeadRecs = -1;
01139 maxTailRecs = -1;
01140
01141 nRecs = cmdparams_get_int(&cmdparams, NRECS, NULL);
01142
01143 if (nRecs < 0)
01144 {
01145 maxTailRecs = -1 * nRecs;
01146 }
01147 else if (nRecs > 0)
01148 {
01149 maxHeadRecs = nRecs;
01150 }
01151 else
01152 {
01153
01154 }
01155
01156
01157 autobangStr = cmdparams_isflagset(&cmdparams, AUTOBANG) ? "[! 1=1 !]" : "";
01158 disableTO = cmdparams_isflagset(&cmdparams, DISABLETO);
01159 }
01160
01161 if (rv == kSetRetStatus_Success)
01162 {
01163
01164
01165
01166 #ifndef DRMS_CLIENT
01167 if (!disableTO && drms_env->dbtimeout == INT_MIN)
01168 {
01169 if (db_settimeout(drms_env->session->db_handle, 600000))
01170 {
01171 fprintf(stderr, "Failed to modify db-statement time-out to %d.\n", 600000);
01172 rv = kSetRetStatus_TimeOut;
01173 }
01174 }
01175 #endif
01176 }
01177
01178 if (rv == kSetRetStatus_Success)
01179 {
01180 if (isAFile(sulist))
01181 {
01182
01183 rv = callSumGet(drms_env, &getChunkFromFile, (void *)sulist, FILE_CHUNK_SIZE, newRetention);
01184 }
01185 else
01186 {
01187 int nsunum;
01188 long long *sunumList = NULL;
01189
01190 nsunum = cmdparams_get_int64arr(&cmdparams, SULIST, (int64_t **)&sunumList, &cpStat);
01191
01192 if (cpStat == CMDPARAMS_SUCCESS)
01193 {
01194
01195 SUSR_List_t listData;
01196
01197 listData.num = nsunum;
01198 listData.arr = sunumList;
01199
01200 rv = callSumGet(drms_env, &getChunkFromList, (void *)&listData, FILE_CHUNK_SIZE, newRetention);
01201 }
01202 else
01203 {
01204
01205 SUSR_Spec_t specData;
01206 char *allvers = NULL;
01207
01208
01209 char **sets = NULL;
01210 DRMS_RecordSetType_t *settypes = NULL;
01211 char **snames = NULL;
01212 char **filts = NULL;
01213 int nsets = 0;
01214 DRMS_RecQueryInfo_t rsinfo;
01215 int inqry;
01216 int atfile;
01217
01218 if (drms_record_parserecsetspec(sulist, &allvers, &sets, &settypes, &snames, &filts, &nsets, &rsinfo) != DRMS_SUCCESS)
01219 {
01220 rv = kSetRetStatus_Spec;
01221 }
01222
01223 if (rv == kSetRetStatus_Success)
01224 {
01225 inqry = ((rsinfo & kFilters) != 0);
01226 atfile = ((rsinfo & kAtFile) != 0);
01227
01228 if (!inqry && maxHeadRecs == -1 && maxTailRecs == -1 && !atfile)
01229 {
01230 fprintf(stderr, "If the 'sulist' argument is a record-set specification, then it must either be an at-file path or the specification must contain a filter. If neither is true, then the record-limit argument (n=XX) must be present.\n");
01231 rv = kSetRetStatus_Argument;
01232 }
01233 }
01234
01235 if (rv == kSetRetStatus_Success)
01236 {
01237 int istat;
01238
01239
01240 if (strlen(autobangStr) > 0)
01241 {
01242 sulist = insertAutoBang(drms_env, sulist, autobangStr, sets, settypes, snames, nsets, &istat);
01243 if (istat)
01244 {
01245 rv = kSetRetStatus_Spec;
01246 }
01247 }
01248
01249 drms_record_freerecsetspecarr(&allvers, &sets, &settypes, &snames, &filts, nsets);
01250
01251 specData.maxHeadRecs = maxHeadRecs;
01252 specData.maxTailRecs = maxTailRecs;
01253 specData.spec = strdup(sulist);
01254
01255 if (specData.spec)
01256 {
01257 rv = callSumGet(drms_env, &getChunkFromSpec, (void *)&specData, FILE_CHUNK_SIZE, newRetention);
01258 free(specData.spec);
01259 specData.spec = NULL;
01260 }
01261 else
01262 {
01263 rv = kSetRetStatus_OutOfMemory;
01264 }
01265 }
01266 }
01267
01268 if (sunumList)
01269 {
01270 free(sunumList);
01271 sunumList = NULL;
01272 }
01273 }
01274 }
01275
01276 return rv;
01277 }