ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/lev0/apps/xingest_lev0.c
Revision: 1.6
Committed: Tue Feb 11 00:31:12 2014 UTC (9 years, 7 months ago) by production
Content type: text/plain
Branch: MAIN
CVS Tags: Ver_9-1, Ver_LATEST, Ver_9-3, Ver_9-41, Ver_9-2, Ver_8-8, Ver_8-6, Ver_8-7, Ver_8-4, Ver_8-5, Ver_9-5, Ver_9-4, Ver_8-10, Ver_8-11, Ver_8-12, Ver_9-0, HEAD
Changes since 1.5: +37 -19 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*-----------------------------------------------------------------------------
2 * cvs/JSOC/proj/lev0/apps/ingest_lev0.c
3 * NOTE: This originally came from hmi_lev0.c on hmi0
4 *-----------------------------------------------------------------------------
5 *
6 * This is a module that runs with DRMS and continuously extracts images and HK
7 * data from .tlm files that appear in the given input dir. It puts the .tlm
8 * and .qac files in the DRMS dataset TLMSERIESNAME and also in the outdir if
9 * given. It extracts images from the .tlm files an puts them in
10 * the DRMS dataset LEV0SERIESNAME and extracts hk data to appropriate hk datasets.
11 *
12 * Call for testing (set TLMSERIESNAME and LEV0SERIESNAME to test datasets):
13 * ingest_lev0 vc=VC05 indir=/scr20/jim/tlm outdir=/scr20/jim/tlm/out [logfile=name]
14 *
15 * OPERATION:
16 * This is normally run on the dedicated lev0 host. Four instances are run.
17 * No outdir= is given, i.e. the .tlm and .qac files only end up in SUMS.
18 *
19 * ingest_lev0 vc=VC02 indir=/dds/socdc/hmi
20 * ingest_lev0 vc=VC05 indir=/dds/socdc/hmi
21 * ingest_lev0 vc=VC10 indir=/dds/socdc/aia
22 * ingest_lev0 vc=VC13 indir=/dds/socdc/aia
23 */
24
25 #include <jsoc_main.h>
26 #include <cmdparams.h>
27 #include <drms.h>
28 #include <drms_names.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include <strings.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #include <sys/stat.h> //for umask(2)
37 #include <dirent.h>
38 #include <unistd.h> //for alarm(2) among other things...
39 #include <printk.h>
40 #include <math.h>
41 #include "packets.h"
42 #include "imgdecode.h"
43 #include "decode_hk_vcdu.h"
44 #include "decode_hk.h"
45 #include "load_hk_config_files.h"
46 #include "add_small_image.c"
47 #include "mypng.h"
48 #include "tdsignals.h"
49 #include "quallev0.h"
50
51 #define RESTART_CNT 2 //#of tlm files to process before restart
52
53 //#define LEV0SERIESNAMEHMI "su_production.lev0d_test"
54 //#define LEV0SERIESNAMEHMI "su_production.lev0f_test"
55 //#define LEV0SERIESNAMEHMI "su_production.lev0f_hmi"
56 ////#define LEV0SERIESNAMEHMI "su_production.lev0f_hmi_test"
57 //For test with DDS on Jan 19, 2010
58 //#define LEV0SERIESNAMEHMI "su_production.lev0f_hmi_JAN2010"
59 //#define LEV0SERIESNAMEHMI "su_production.lev0f_hmi_junk"
60 //#define LEV0SERIESNAMEHMI "hmi.lev0f"
61 ////#define TLMSERIESNAMEHMI "su_production.tlm_test"
62 //For test with DDS on Jan 19, 2010
63 //#define TLMSERIESNAMEHMI "su_production.tlm_hmi_JAN2010"
64 //#define TLMSERIESNAMEHMI "su_production.tlm_hmi_junk"
65
66 #define LEV0SERIESNAMEHMIGND "hmi_ground.lev0_dds"
67 #define TLMSERIESNAMEHMIGND "hmi_ground.tlm_dds"
68 //#define TLMSERIESNAMEHMI "hmi.tlm_reingest"
69
70 //#define LEV0SERIESNAMEAIA "su_production.lev0d_test_aia"
71 //#define LEV0SERIESNAMEAIA "su_production.lev0f_aia"
72 ////#define LEV0SERIESNAMEAIA "aia.lev0f"
73 //For test with DDS on Jan 19, 2010
74 //#define LEV0SERIESNAMEAIA "su_production.lev0f_aia_JAN2010"
75 //#define LEV0SERIESNAMEAIA "su_production.lev0f_aia_junk"
76 ////#define TLMSERIESNAMEAIA "su_production.tlm_test_aia"
77 //For test with DDS on Jan 19, 2010
78 //#define TLMSERIESNAMEAIA "su_production.tlm_aia_JAN2010"
79 //#define TLMSERIESNAMEAIA "su_production.tlm_aia_junk"
80
81 #define LEV0SERIESNAMEAIAGND "aia_ground.lev0_dds"
82 #define TLMSERIESNAMEAIAGND "aia_ground.tlm_dds"
83 //#define TLMSERIESNAMEAIA "aia.tlm_reingest"
84
85 //#define LEV0SERIESNAMEHMI "hmi.lev0_60d"
86 //#define TLMSERIESNAMEHMI "hmi.tlm_60d"
87 //#define LEV0SERIESNAMEAIA "aia.lev0_60d"
88 //#define TLMSERIESNAMEAIA "aia.tlm_60d"
89
90 //When change to these data series below to save real data.
91 //#define TLMSERIESNAMEHMI "hmi.tlm"
92 #define TLMSERIESNAMEHMI "su_production.tlm"
93 //#define LEV0SERIESNAMEHMI "hmi.lev0a"
94 #define LEV0SERIESNAMEHMI "su_production.lev0a"
95 #define LEV0SERIESNAMEAIA "aia.lev0"
96 #define TLMSERIESNAMEAIA "aia.tlm"
97
98 //#define LEV0SERIESNAMEAIA "aia.lev0d"
99 //#define TLMSERIESNAMEAIA "aia.tlmd"
100 //#define LEV0SERIESNAMEHMI "hmi.lev0d"
101 //#define TLMSERIESNAMEHMI "hmi.tlmd"
102
103 //#define LEV0SERIESNAMEAIA "aia.lev0e"
104 //#define TLMSERIESNAMEAIA "aia.tlme"
105 //#define LEV0SERIESNAMEHMI "hmi.lev0e"
106 //#define TLMSERIESNAMEHMI "hmi.tlme"
107
108 //Also, change setting in $JSOCROOT/proj/lev0/apps/SOURCE_ENV_HK_DECODE file to:
109 //setenv HK_LEV0_BY_APID_DATA_ID_NAME lev0
110 //setenv HK_DF_HSB_DIRECTORY /tmp21/production/lev0/hk_hsb_dayfile
111 //setenv HK_JSVNMAP_DIRECTORY /home/production/cvs/TBL_JSOC/lev0/hk_jsn_map_file/prod
112
113
114 #define H0LOGFILE "/usr/local/logs/lev0/ingest_lev0.%s.%s.%s.log"
115 #define PKTSZ 1788 //size of VCDU pkt
116 #define MAXFILES 65535 //max # of file can handle in tlmdir
117 #define NUMTIMERS 8 //number of seperate timers avail
118 #define IMAGE_NUM_COMMIT 12 //number of complete images until commit
119 //#define IMAGE_NUM_COMMIT 2 //!!TEMP number of complete images until commit
120 #define TESTAPPID 0x199 //appid of test pattern packet
121 #define TESTVALUE 0xc0b //first value in test pattern packet
122 #define MAXERRMSGCNT 10 //max # of err msg before skip the tlm file
123 #define NOTSPECIFIED "***NOTSPECIFIED***"
124 #define ENVFILE "/home/production/cvs/JSOC/proj/lev0/apps/SOURCE_ENV_FOR_HK_DECODE"
125 #define ENVFILE_GND "/home/production/cvs/JSOC/proj/lev0/apps/SOURCE_ENV_FOR_HK_DECODE_GROUND"
126
127 extern int decode_next_hk_vcdu(unsigned short *tbuf, CCSDS_Packet_t **hk, unsigned int *Fsn);
128 extern int write_hk_to_drms();
129 extern void HMI_compute_exposure_times(DRMS_Record_t *rec, HK_Keyword_t *isp, int flg);
130 extern int set_HMI_mech_values(DRMS_Record_t *rec);
131 static TIME SDO_to_DRMS_time(int sdo_s, int sdo_ss);
132
133 // List of default parameter values.
134 ModuleArgs_t module_args[] = {
135 {ARG_STRING, "vc", NOTSPECIFIED, "Primary virt channel to listen to"},
136 {ARG_STRING, "indir", NOTSPECIFIED, "directory containing the files to ingest"},
137 {ARG_STRING, "outdir", NOTSPECIFIED, "directory to move the files to after the ingest"},
138 {ARG_STRING, "logfile", NOTSPECIFIED, "optional log file name. Will create one if not given"},
139 {ARG_FLAG, "v", "0", "verbose flag"},
140 {ARG_FLAG, "h", "0", "help flag"},
141 {ARG_FLAG, "r", "0", "restart flag"},
142 {ARG_FLAG, "g", "0", "ground data flag"},
143 {ARG_END}
144 };
145
146 CmdParams_t cmdparams;
147 // Module name presented to DRMS.
148 char *module_name = "ingest_lev0";
149
150 typedef enum
151 {
152 kThreadSigErr_Success
153 } ThreadSigErr_t;
154 static int gLoop = 1;
155 static pthread_mutex_t mutex;
156 static struct timeval tv0;
157 static td_alarm_t talarm = 0;
158
159 FILE *h0logfp; // fp for h0 ouput log for this run
160 static IMG Image, ImageOld;
161 static IMG *Img, *ImgO, *ImgC;
162 static CCSDS_Packet_t *Hk;
163 static DRMS_Record_t *rs;
164 static DRMS_Segment_t *segment;
165 static DRMS_Array_t *segArray;
166 static DRMS_RecordSet_t *rset;
167 static DRMS_Record_t *rs_old, *rsc;
168 static DRMS_Segment_t *segmentc;
169 static DRMS_Array_t *cArray, *oldArray;
170 static TIME sdo_epoch;
171 static char datestr[32];
172 static char bld_vers[16];
173 static struct timeval first[NUMTIMERS], second[NUMTIMERS];
174
175 int INVALtime;
176 unsigned int fsn = 0;
177 unsigned int fsnx = 0;
178 unsigned int fsn_prev = 0;
179 unsigned int fsn_pre_rexmit = 0;
180 unsigned int fid = 0;
181
182 short *rdat;
183 long long vcdu_seq_num;
184 long long vcdu_seq_num_next;
185 long long total_missing_im_pdu;
186 unsigned int vcdu_24_cnt, vcdu_24_cnt_next;
187 int verbose;
188 int grounddata;
189 int appid;
190 int testid1, testid2;
191 int hmiaiaflg; //0=hmi, 1=aia
192 int whk_status;
193 int total_tlm_vcdu;
194 int total_missing_vcdu;
195 int errmsgcnt, fileimgcnt;
196 int cntsleeps = 0;
197 int paused = 0;
198 int imagecnt = 0; // num of images since last commit
199 int restartflg = 0; // set when ingest_lev0 is called for a restart
200 int abortflg = 0;
201 int sigalrmflg = 0; // set on signal so prog will know
202 int ignoresigalrmflg = 0; // set after a close_image()
203 int firstfound = 0; // set if see any file after startup
204 int rexmitmode = 0; // set if this process is doing /rexmit dir
205 int ALRMSEC = 60; // must get 2 in a row for no image timeout
206 int sleep_interval = 2; // #of sec to sleep after do_ingest() calls
207 char logname[128];
208 char argvc[32], argindir[96], arglogfile[96], argoutdir[96];
209 char timetag[32];
210 char pchan[8]; // primary channel to listen to e.g. VC02
211 char rchan[8]; // redundant channel to listen to e.g. VC10
212 char stopfile[80]; // e.g. /usr/local/logs/lev0/VC04_stop
213 char tlmseriesname[128]; // e.g. hmi.tlm
214 char lev0seriesname[128]; // e.g. hmi.lev0
215 char tlmnamekey[128]; // shortened tlm file name for TLMDSNAM keyword
216 char tlmnamekeyfirst[128]; // for TLMDSNAM keyword for 1st file of image
217 char oldtlmdsnam[128]; // TLMDSNAM keyword from prev rec in db
218 char *username; // from getenv("USER")
219 char *tlmdir; // tlm dir name passed in
220 char *outdir; // output dir for .tlm file (can be /dev/null)
221 char *logfile; // optional log name passed in
222 char *vc; // virtual channel to process, e.g. VC02
223 struct stat stbuf;
224 struct p_r_chans {
225 char *pchan;
226 char *rchan;
227 int instru; //0=hmi, 1=aia
228 };
229 typedef struct p_r_chans P_R_CHANS;
230
231 P_R_CHANS p_r_chan_pairs[] = {
232 {"VC01", "VC09", 1}, // AIA
233 {"VC04", "VC12", 1}, // AIA
234 {"VC02", "VC10", 0}, // HMI
235 {"VC05", "VC13", 0}, // HMI
236 {"n/a", "n/a"}
237 };
238
239 struct namesort { // sorted file names in tlmdir
240 char *name;
241 };
242 typedef struct namesort NAMESORT;
243
244
245 //Function callback that gets called when alarm 'rings'. This runs in the signal
246 //thread that receives, the alarm signal, not the main thread. */
247 void shandler(int sig, pthread_mutex_t *mtx)
248 {
249 float elapsed;
250 struct timeval tv1;
251 gettimeofday(&tv1, NULL);
252
253 elapsed = (float)((tv1.tv_sec * 1000000.0 + tv1.tv_usec -
254 (tv0.tv_sec * 1000000.0 + tv0.tv_usec)) / 1000000.0);
255
256 printk("Thread '%lld' received alarm signal '%d'.\n",
257 (long long )pthread_self(), sig);
258 printk("Elapsed time is %f seconds.\n", elapsed);
259
260 /* This isn't in the main thread, so put globals in a critical region. */
261 pthread_mutex_lock(mtx);
262 sigalrmflg = 1;
263 pthread_mutex_unlock(mtx);
264 }
265
266 int nice_intro ()
267 {
268 int usage = cmdparams_get_int (&cmdparams, "h", NULL);
269 if (usage)
270 {
271 printf ("Usage:\ningest_lev0 [-vh] "
272 "vc=<virt chan> indir=</dir> [outdir=</dir>] [logfile=<file>]\n"
273 " -h: help - show this message then exit\n"
274 " -v: verbose\n"
275 " -g: output to hmi_ground/aia_ground\n"
276 " -r: restart. only used when we restart our selves periodically\n"
277 "vc= primary virt channel to listen to e.g. VC02\n"
278 "indir= directory containing the files to ingest\n"
279 "outdir= optional dir to copy the files to after the ingest\n"
280 "logfile= optional log file name. Will create one if not given\n");
281 return(1);
282 }
283 verbose = cmdparams_get_int (&cmdparams, "v", NULL);
284 grounddata = cmdparams_get_int (&cmdparams, "g", NULL);
285 restartflg = cmdparams_get_int (&cmdparams, "r", NULL);
286 return (0);
287 }
288
289 TIME SDO_to_DRMS_time(int sdo_s, int sdo_ss)
290 {
291 static int firstcall = 1;
292 if (firstcall)
293 {
294 firstcall = 0;
295 }
296 /* XXX fix build 3/18/2008, arta */
297 return(sdo_epoch + (TIME)sdo_s + (TIME)(sdo_ss)/65536.0);
298 }
299
300 // Setup global datestr[] like: 2008.07.14_08:29:31
301 char *do_datestr() {
302 time_t tval;
303 struct tm *t_ptr;
304
305 tval = time(NULL);
306 t_ptr = localtime(&tval);
307 sprintf(datestr, "%d.%02d.%02d_%02d:%02d:%02d",
308 (t_ptr->tm_year+1900), (t_ptr->tm_mon+1),
309 t_ptr->tm_mday, t_ptr->tm_hour, t_ptr->tm_min, t_ptr->tm_sec);
310 return(datestr);
311 }
312
313 // Returns a time tag like yyyy.mm.dd.hhmmss
314 char *gettimetag()
315 {
316 struct timeval tvalr;
317 struct tm *t_ptr;
318
319 gettimeofday(&tvalr, NULL);
320 t_ptr = localtime((const time_t *)&tvalr);
321 sprintf(timetag, "%04d.%02d.%02d.%02d%02d%02d",
322 (t_ptr->tm_year+1900), (t_ptr->tm_mon+1), t_ptr->tm_mday, t_ptr->tm_hour, t_ptr->tm_min, t_ptr->tm_sec);
323 return(timetag);
324 }
325
326
327 void BeginTimer(int n)
328 {
329 gettimeofday (&first[n], NULL);
330 }
331
332 float EndTimer(int n)
333 {
334 gettimeofday (&second[n], NULL);
335 if (first[n].tv_usec > second[n].tv_usec) {
336 second[n].tv_usec += 1000000;
337 second[n].tv_sec--;
338 }
339 return (float) (second[n].tv_sec-first[n].tv_sec) +
340 (float) (second[n].tv_usec-first[n].tv_usec)/1000000.0;
341 }
342
343 // Outputs the variable format message (re: printf) to the log file.
344 int h0log(const char *fmt, ...)
345 {
346 va_list args;
347 char string[32768];
348
349 va_start(args, fmt);
350 vsprintf(string, fmt, args);
351 if(h0logfp) {
352 fprintf(h0logfp, string);
353 fflush(h0logfp);
354 } else { // couldn't open log
355 printf(string);
356 fflush(stdout);
357 }
358 va_end(args);
359 return(0);
360 }
361
362 int send_mail(char *fmt, ...)
363 {
364 va_list args;
365 char string[1024], cmd[1024];
366
367 va_start(args, fmt);
368 vsprintf(string, fmt, args);
369 sprintf(cmd, "echo \"%s\" | Mail -s \"ingest_lev0 mail\" jsoc_ops", string);
370 system(cmd);
371 va_end(args);
372 return(0);
373 }
374
375 //Set the QUALLEV0 keyword
376 void do_quallev0(DRMS_Record_t *rs, IMG *img, int fsn)
377 {
378 char *hwltnset, *cdark;
379 char *hseqerr, *aistate;
380 char wave_str[16];
381 int status, hsqfgsn, asqfsn, hgp1rgst;
382 float percentd;
383 uint32_t missvals, datav;
384 uint32_t hcf1encd, hcf2encd, hps1encd, hps2encd, hps3encd;
385 uint32_t hwt1encd, hwt2encd, hwt3encd, hwt4encd;
386 uint32_t hcf1pos, hcf2pos, hpl1pos, hpl2pos, hpl3pos, hwl1pos, hwl2pos;
387 uint32_t hwl3pos, hwl4pos;
388 uint32_t aiawvlen, aifwen, aiasen;
389 short aifiltyp;
390 uint32_t quallev0 = 0;
391 uint32_t qmiss = 0;
392
393 if(img->overflow) quallev0 = quallev0 | Q_OVFL;
394 if(img->headerr) quallev0 = quallev0 | Q_HDRERR;
395 if(img->nerrors) quallev0 = quallev0 | Q_CMPERR;
396 if(img->last_pix_err) quallev0 = quallev0 | Q_LPXERR;
397 if(img->reopened) quallev0 = quallev0 | Q_REOPENED;
398 missvals = img->totalvals - img->datavals;
399 if(missvals > 0) quallev0 = quallev0 | Q_MISS0;
400 datav = img->totalvals;
401 if(missvals > (uint32_t)(datav * 0.01)) quallev0 = quallev0 | Q_MISS1;
402 if(missvals > (uint32_t)(datav * 0.05)) quallev0 = quallev0 | Q_MISS2;
403 if(missvals > (uint32_t)(datav * 0.25)) quallev0 = quallev0 | Q_MISS3;
404 if(missvals == datav) quallev0 = quallev0 | Q_MISSI;
405 if(img->datavals == 0) quallev0 = quallev0 | Q_MISSALL; //high bit, no data
406
407 // if(missvals != 0) {
408 // qmiss = (uint32_t)(0.84 * log(missvals/img->totalvals)) + 15;
409 // qmiss = qmiss & 0x0f; //need this?
410 // qmiss = qmiss * 256; //bits 8-11
411 // quallev0 = quallev0 | qmiss;
412 // }
413
414 if(fsn == 469769216) quallev0 = quallev0 | Q_CORRUPT; //corrupt image
415 if(INVALtime) quallev0 = quallev0 | Q_INVALTIME;
416 if(cdark = drms_getkey_string(rs, "IMG_TYPE", &status)) {
417 if(!strcmp(cdark, "DARK")) quallev0 = quallev0 | Q_DARK;
418 free(cdark);
419 }
420 if(!hmiaiaflg) { //HMI specific qual bits
421 hsqfgsn = drms_getkey_int(rs, "HSQFGSN", &status);
422 if(status || (fsn != hsqfgsn)) quallev0 = quallev0 | Q_NOISP;
423 //Removed per Rock's email Re: lev0 quality updates 9Jun2010 10:22
424 //if(hseqerr = drms_getkey_string(rs, "HSEQERR", &status)) {
425 // if(strcmp(hseqerr, "SUCCESS")) quallev0 = quallev0 | Q_SEQERR;
426 // free(hseqerr);
427 //}
428 if(hwltnset = drms_getkey_string(rs, "HWLTNSET", &status)) {
429 if(!strcmp(hwltnset, "OPEN")) quallev0 = quallev0 | Q_ISSOPEN;
430 free(hwltnset);
431 }
432 hcf1encd = drms_getkey_int(rs, "HCF1ENCD", &status);
433 hcf1pos = drms_getkey_int(rs, "HCF1POS", &status);
434 //if(!((hcf1encd == hcf1pos) || (hcf1encd == hcf1pos+1) || (hcf1encd == hcf1pos-1)))
435 if(!((hcf1encd == hcf1pos) || (hcf1encd == hcf1pos-1)))
436 quallev0 = quallev0 | Q_HCF1ENCD;
437 hcf2encd = drms_getkey_int(rs, "HCF2ENCD", &status);
438 hcf2pos = drms_getkey_int(rs, "HCF2POS", &status);
439 //if(!((hcf2encd == hcf2pos) || (hcf2encd == hcf2pos+1) || (hcf2encd == hcf2pos-1)))
440 if(!((hcf2encd == hcf2pos) || (hcf2encd == hcf2pos-1)))
441 quallev0 = quallev0 | Q_HCF2ENCD;
442 hps1encd = drms_getkey_int(rs, "HPS1ENCD", &status);
443 hpl1pos = drms_getkey_int(rs, "HPL1POS", &status);
444 if(!((hpl1pos == hps1encd) || (hpl1pos == (hps1encd+1) % 240)))
445 quallev0 = quallev0 | Q_HPS1ENCD;
446 hps2encd = drms_getkey_int(rs, "HPS2ENCD", &status);
447 hpl2pos = drms_getkey_int(rs, "HPL2POS", &status);
448 if(!((hpl2pos == hps2encd) || (hpl2pos == (hps2encd+1) % 240)))
449 quallev0 = quallev0 | Q_HPS2ENCD;
450 hps3encd = drms_getkey_int(rs, "HPS3ENCD", &status);
451 hpl3pos = drms_getkey_int(rs, "HPL3POS", &status);
452 if(!((hpl3pos == hps3encd) || (hpl3pos == (hps3encd+1) % 240)))
453 quallev0 = quallev0 | Q_HPS3ENCD;
454 hwt1encd = drms_getkey_int(rs, "HWT1ENCD", &status);
455 hwl1pos = drms_getkey_int(rs, "HWL1POS", &status);
456 if(!((hwl1pos == hwt1encd) || (hwl1pos == (hwt1encd+1) % 240)))
457 quallev0 = quallev0 | Q_HWT1ENCD;
458 hwt2encd = drms_getkey_int(rs, "HWT2ENCD", &status);
459 hwl2pos = drms_getkey_int(rs, "HWL2POS", &status);
460 if(!((hwl2pos == hwt2encd) || (hwl2pos == (hwt2encd+1) % 240)))
461 quallev0 = quallev0 | Q_HWT2ENCD;
462 hwt3encd = drms_getkey_int(rs, "HWT3ENCD", &status);
463 hwl3pos = drms_getkey_int(rs, "HWL3POS", &status);
464 if(!((hwl3pos == hwt3encd) || (hwl3pos == (hwt3encd+1) % 240)))
465 quallev0 = quallev0 | Q_HWT3ENCD;
466 hwt4encd = drms_getkey_int(rs, "HWT4ENCD", &status);
467 hwl4pos = drms_getkey_int(rs, "HWL4POS", &status);
468 if(!((hwl4pos == hwt4encd) || (hwl4pos == (hwt4encd+1) % 240)))
469 quallev0 = quallev0 | Q_HWT4ENCD;
470 //New 14Aug2013
471 hgp1rgst = drms_getkey_int(rs, "HGP1RGST", &status);
472 if(hgp1rgst != DRMS_MISSING_INT) {
473 hgp1rgst = (hgp1rgst << 28) & 0x30000000;
474 quallev0 = quallev0 | hgp1rgst;
475 }
476 }
477 else { //AIA specific qual bits
478 asqfsn = drms_getkey_int(rs, "ASQFSN", &status);
479 if(fsn != asqfsn) quallev0 = quallev0 | Q_NOISP;
480 if(aistate = drms_getkey_string(rs, "AISTATE", &status)) {
481 if(!strcmp(aistate, "OPEN")) quallev0 = quallev0 | AQ_ISSOPEN;
482 free(aistate);
483 }
484 strcpy(wave_str, "UNKNOWN");
485 aiawvlen = drms_getkey_int(rs, "AIAWVLEN", &status);
486 aifiltyp = drms_getkey_short(rs, "AIFILTYP", &status);
487 aifwen = drms_getkey_int(rs, "AIFWEN", &status);
488 aiasen = drms_getkey_int(rs, "AIASEN", &status);
489 switch(aiawvlen) {
490 case 9: //9.4
491 if(aifiltyp == 0) {
492 if((aifwen != 269) && (aifwen != 270)) {
493 quallev0 = quallev0 | A94Mech_Err;
494 }
495 }
496 else if(aifiltyp == 1) {
497 if((aifwen != 11) && (aifwen != 12)) {
498 quallev0 = quallev0 | A94Mech_Err;
499 }
500 }
501 else if(aifiltyp == 2) {
502 if((aifwen != 74) && (aifwen != 75)) {
503 quallev0 = quallev0 | A94Mech_Err;
504 }
505 }
506 //All the wave_str code can be compacted, but I'm keeping it
507 //symetric with Rock's notes
508 if((aifwen == 269) || (aifwen == 270)) {
509 strcpy(wave_str, "94_THIN");
510 }
511 else if((aifwen == 11) || (aifwen == 12)) {
512 strcpy(wave_str, "94_THICK");
513 }
514 else if((aifwen == 74) || (aifwen == 75)) {
515 strcpy(wave_str, "94_OPEN");
516 }
517 break;
518 case 1: //13.1
519 if(aifiltyp == 0) {
520 if((aifwen != 269) && (aifwen != 270)) {
521 quallev0 = quallev0 | A131Mech_Err;
522 }
523 }
524 else if(aifiltyp == 1) {
525 if((aifwen != 11) && (aifwen != 12)) {
526 quallev0 = quallev0 | A131Mech_Err;
527 }
528 }
529 else if(aifiltyp == 2) {
530 if((aifwen != 74) && (aifwen != 75)) {
531 quallev0 = quallev0 | A131Mech_Err;
532 }
533 }
534 if((aifwen == 269) || (aifwen == 270)) {
535 strcpy(wave_str, "131_THIN");
536 }
537 else if((aifwen == 11) || (aifwen == 12)) {
538 strcpy(wave_str, "131_THICK");
539 }
540 else if((aifwen == 74) || (aifwen == 75)) {
541 strcpy(wave_str, "131_OPEN");
542 }
543 break;
544 case 7: //17.1
545 if(aifiltyp == 0) {
546 if((aifwen != 203) && (aifwen != 204)) {
547 quallev0 = quallev0 | A171Mech_Err;
548 }
549 }
550 else if(aifiltyp == 1) {
551 if((aifwen != 11) && (aifwen != 12)) {
552 quallev0 = quallev0 | A171Mech_Err;
553 }
554 }
555 else if(aifiltyp == 2) {
556 //NOTE: no 171_OPEN
557 if((aifwen != 74) && (aifwen != 75)) {
558 quallev0 = quallev0 | A171Mech_Err;
559 }
560 }
561 if((aifwen == 203) || (aifwen == 204)) {
562 strcpy(wave_str, "171_THIN");
563 }
564 else if((aifwen == 11) || (aifwen == 12)) {
565 strcpy(wave_str, "171_THICK");
566 }
567 break;
568 /* !!!TBD fix below like did above after resolve MIX_THIN stuff w/Rock */
569 case 3: //19.3
570 if(aifiltyp == 0) {
571 if(aiasen != 6) {
572 quallev0 = quallev0 | A193Mech_Err;
573 }
574 if((aifwen != 269) && (aifwen != 270)) {
575 quallev0 = quallev0 | A193Mech_Err;
576 }
577 }
578 else if(aifiltyp == 1) {
579 if(aiasen != 6) {
580 quallev0 = quallev0 | A193Mech_Err;
581 }
582 if((aifwen != 11) && (aifwen != 12)) {
583 quallev0 = quallev0 | A193Mech_Err;
584 }
585 }
586 else if(aifiltyp == 2) {
587 if(aiasen != 6) {
588 quallev0 = quallev0 | A193Mech_Err;
589 }
590 if((aifwen != 74) && (aifwen != 75)) {
591 quallev0 = quallev0 | A193Mech_Err;
592 }
593 }
594 if(aiasen == 6) {
595 if((aifwen == 269) || (aifwen == 270)) {
596 strcpy(wave_str, "193_THIN");
597 } else if((aifwen == 11) || (aifwen == 12)) {
598 strcpy(wave_str, "193_THICK");
599 } else if((aifwen == 74) || (aifwen == 75)) {
600 strcpy(wave_str, "193_OPEN");
601 }
602 }
603 else {
604 if((aifwen == 269) || (aifwen == 270)) {
605 strcpy(wave_str, "MIX_THIN");
606 } else if((aifwen == 11) || (aifwen == 12)) {
607 strcpy(wave_str, "MIX_THICK");
608 } else if((aifwen == 74) || (aifwen == 75)) {
609 strcpy(wave_str, "MIX_OPEN");
610 }
611 }
612 break;
613 case 2: //21.1
614 if(aifiltyp == 0) {
615 if(aiasen != 24) {
616 quallev0 = quallev0 | A211Mech_Err;
617 }
618 if((aifwen != 203) && (aifwen != 204)) {
619 quallev0 = quallev0 | A211Mech_Err;
620 }
621 }
622 else if(aifiltyp == 1) {
623 if(aiasen != 24) {
624 quallev0 = quallev0 | A211Mech_Err;
625 }
626 if((aifwen != 137) && (aifwen != 138)) {
627 quallev0 = quallev0 | A211Mech_Err;
628 }
629 }
630 else if(aifiltyp == 2) {
631 if(aiasen != 24) {
632 quallev0 = quallev0 | A211Mech_Err;
633 }
634 if((aifwen != 74) && (aifwen != 75)) {
635 quallev0 = quallev0 | A211Mech_Err;
636 }
637 }
638 if(aiasen == 24) {
639 if((aifwen == 203) || (aifwen == 204)) {
640 strcpy(wave_str, "211_THIN");
641 } else if((aifwen == 137) || (aifwen == 138)) {
642 strcpy(wave_str, "211_THICK");
643 } else if((aifwen == 74) || (aifwen == 75)) {
644 strcpy(wave_str, "211_OPEN");
645 }
646 }
647 else {
648 if((aifwen == 203) || (aifwen == 204)) {
649 strcpy(wave_str, "MIX_THIN");
650 } else if((aifwen == 137) || (aifwen == 138)) {
651 strcpy(wave_str, "MIX_THICK");
652 } else if((aifwen == 74) || (aifwen == 75)) {
653 strcpy(wave_str, "MIX_OPEN");
654 }
655 }
656 break;
657 case 8: //30.4
658 if(aifiltyp == 0) {
659 if((aifwen != 203) && (aifwen != 204)) {
660 quallev0 = quallev0 | A304Mech_Err;
661 }
662 }
663 else if(aifiltyp == 1) {
664 if((aifwen != 137) && (aifwen != 138)) {
665 quallev0 = quallev0 | A304Mech_Err;
666 }
667 }
668 else if(aifiltyp == 2) {
669 if((aifwen != 74) && (aifwen != 75)) {
670 quallev0 = quallev0 | A304Mech_Err;
671 }
672 }
673 if((aifwen == 203) || (aifwen == 204)) {
674 strcpy(wave_str, "304_THIN");
675 } else if((aifwen == 137) || (aifwen == 138)) {
676 strcpy(wave_str, "304_THICK");
677 } else if((aifwen == 74) || (aifwen == 75)) {
678 strcpy(wave_str, "304_OPEN");
679 }
680 break;
681 case 0: //33.5
682 if(aifiltyp == 0) {
683 if((aifwen != 203) && (aifwen != 204)) {
684 quallev0 = quallev0 | A335Mech_Err;
685 }
686 }
687 else if(aifiltyp == 1) {
688 if((aifwen != 137) && (aifwen != 138)) {
689 quallev0 = quallev0 | A335Mech_Err;
690 }
691 }
692 else if(aifiltyp == 2) {
693 if((aifwen != 74) && (aifwen != 75)) {
694 quallev0 = quallev0 | A335Mech_Err;
695 }
696 }
697 if((aifwen == 203) || (aifwen == 204)) {
698 strcpy(wave_str, "335_THIN");
699 } else if((aifwen == 137) || (aifwen == 138)) {
700 strcpy(wave_str, "335_THICK");
701 } else if((aifwen == 74) || (aifwen == 75)) {
702 strcpy(wave_str, "335_OPEN");
703 }
704 break;
705 case 4: //160.0
706 if((aifwen != 269) && (aifwen != 270)) {
707 quallev0 = quallev0 | A160Mech_Err;
708 }
709 else strcpy(wave_str, "1600");
710 break;
711 case 5: //170.0
712 if((aifwen != 137) && (aifwen != 138)) {
713 quallev0 = quallev0 | A170Mech_Err;
714 }
715 else strcpy(wave_str, "1700");
716 break;
717 case 6: //450.0
718 if((aifwen != 74) && (aifwen != 75)) {
719 quallev0 = quallev0 | A450Mech_Err;
720 }
721 else strcpy(wave_str, "4500");
722 break;
723 }
724 if(!strcmp(wave_str, "UNKNOWN")) quallev0 = quallev0 | AQ_INVAL_WL;
725 }
726 //drms_setkey_int(rs, "QUALLEV0", quallev0); //don't use this anymore
727 drms_setkey_int(rs, "QUALITY", quallev0);
728 drms_setkey_string(rs, "BLD_VERS", bld_vers); //build vers to every record
729 drms_setkey_string(rs, "WAVE_STR", wave_str);
730 percentd = (float)((100.0 * (float)img->datavals)/(float)img->totalvals);
731 drms_setkey_float(rs, "PERCENTD", percentd);
732 }
733
734 // Close out an image.
735 void close_image(DRMS_Record_t *rs, DRMS_Segment_t *seg, DRMS_Array_t *array,
736 IMG *img, int fsn)
737 {
738 STAT stat;
739 int status, n, k;
740 uint32_t missvals;
741 long long cmdx;
742 char tlmdsname[128];
743
744 printk("*Closing image for fsn = %u\n", fsn);
745 if(imgstat(img, &stat)) {
746 printk("**Error on imgstat() for fsn = %u\n", fsn);
747 }
748 else {
749 drms_setkey_short(rs, "DATAMIN", stat.min);
750 drms_setkey_short(rs, "DATAMAX", stat.max);
751 drms_setkey_short(rs, "DATAMEDN", stat.median);
752 drms_setkey_float(rs, "DATAMEAN", stat.mean);
753 drms_setkey_float(rs, "DATARMS", stat.rms);
754 drms_setkey_float(rs, "DATASKEW", stat.skew);
755 drms_setkey_float(rs, "DATAKURT", stat.kurt);
756 }
757 // CAMERA set by HMI_compute_exposure_times()
758 if(hmiaiaflg) { // except for AIA use telnum
759 drms_setkey_int(rs, "CAMERA", (img->telnum)+1);
760 cmdx = drms_getkey_longlong(rs, "AIMGSHCE", &status);
761 if (0 == cmdx) drms_setkey_int(rs, "AIMGTYP", 1);
762 }
763 drms_setkey_int(rs, "IMGAPID", img->apid);
764 drms_setkey_int(rs, "CROPID", img->cropid);
765 if(drms_setkey_int(rs, "LUTID", img->luid)) {
766 printk("ERROR on setkey_int for LUTID\n");
767 }
768 drms_setkey_int(rs, "TAPCODE", img->tap);
769 n = (img->N) & 0x1F;
770 n = n << 3;
771 k = (img->K) & 0x07;
772 if(img->N == 16) {
773 drms_setkey_int(rs, "COMPID", 0);
774 drms_setkey_int(rs, "BITSELID", 0);
775 }
776 else {
777 drms_setkey_int(rs, "COMPID", n+k);
778 drms_setkey_int(rs, "BITSELID", img->R);
779 }
780 drms_setkey_int(rs, "FID", img->fid);
781 drms_setkey_int(rs, "TOTVALS", img->totalvals);
782 drms_setkey_int(rs, "DATAVALS", img->datavals);
783 drms_setkey_int(rs, "NPACKETS", img->npackets);
784 drms_setkey_int(rs, "NERRORS", img->nerrors);
785 drms_setkey_short(rs, "EOIERROR", img->last_pix_err);
786 drms_setkey_short(rs, "HEADRERR", img->headerr);
787 drms_setkey_short(rs, "OVERFLOW", img->overflow);
788 missvals = img->totalvals - img->datavals;
789 drms_setkey_int(rs, "MISSVALS", missvals);
790 snprintf(tlmdsname, 128, "%s[%s]", tlmseriesname, tlmnamekeyfirst);
791 drms_setkey_string(rs, "TLMDSNAM", tlmdsname);
792 unsigned int pts = img->first_packet_time >> 16;
793 int ptss = img->first_packet_time & 0xffff;
794 TIME fpt = SDO_to_DRMS_time(pts, ptss);
795 drms_setkey_double(rs, "IMGFPT", fpt);
796 drms_setkey_double(rs, "DATE", CURRENT_SYSTEM_TIME);
797 do_quallev0(rs, img, fsn); //set the QUALLEV0 keyword
798
799 status = drms_segment_write(seg, array, 0);
800 if (status) {
801 printk("ERROR: drms_segment_write error=%d for fsn=%u\n", status, fsn);
802 }
803 add_small_array(rs, array, 8, 16); //add Phil's png and small fits
804 array->data = NULL; // must do before free
805 drms_free_array(array);
806 if((status = drms_close_record(rs, DRMS_INSERT_RECORD))) {
807 printk("**ERROR: drms_close_record failed for %s fsn=%u\n",
808 lev0seriesname, fsn);
809 }
810 img->initialized = 0; //indicate image is ready for use again
811 //imgdecode_init_hack(img);
812 }
813
814 // Got a fatal error.
815 void abortit(int stat)
816 {
817 printk("***Abort in progress ...\n");
818 printk("**Exit ingest_lev0 w/ status = %d\n", stat);
819 if (h0logfp) fclose(h0logfp);
820 exit(stat);
821 }
822
823
824 int compare_names(const void *a, const void *b)
825 {
826 NAMESORT *x=(NAMESORT *)a, *y=(NAMESORT *)b;
827 return(strcmp(x->name+4, y->name+4)); // skip VC02/VC05 in compare
828 }
829
830 unsigned short MDI_getshort (unsigned char *c) // machine independent
831 {
832 unsigned short s = 0;
833
834 s = (unsigned short) *c++ << 8;
835 s |= (unsigned short) *c;
836 return s;
837 }
838
839 //fsn_normal_new_image()
840 int fsn_normal_new_image()
841 {
842 int dstatus, i;
843
844 // start a new image
845 Img->initialized = 0;
846 Img->reopened = 0;
847 errmsgcnt = 0;
848 fsn_prev = fsnx;
849 sprintf(tlmnamekeyfirst, "%s", tlmnamekey); //save for TLMDSNAM
850 rs = drms_create_record(drms_env, lev0seriesname, DRMS_PERMANENT, &dstatus);
851 if(dstatus) {
852 if(dstatus == DRMS_ERROR_SUMOPEN) {
853 printk("**ERROR: DRMS can't open w/SUMS. Aborting...\n");
854 abortit(4);
855 }
856 printk("**ERROR: Can't create record for %s fsn=%u\n", lev0seriesname, fsnx);
857 return(1);
858 }
859 dstatus = drms_setkey_int(rs, "FSN", fsnx);
860 if(!(segment = drms_segment_lookup(rs, "image"))) {
861 printk("No drms_segment_lookup(rs, image)\n");
862 return(1);
863 }
864 //must initialize Img in case no data pkt comes in for this image
865 #if 0
866 Img->datavals = 0;
867 Img->npackets = 0;
868 Img->nerrors = 0;
869 Img->last_pix_err = 0;
870 Img->first_packet_time = UINT64_MAX;
871 for (i = 0; i < MAXPIXELS; ++i)
872 Img->dat[i] = BLANK;
873 for (i = 0; i < MAXHIST; ++i)
874 Img->hist[i] = 0;
875 #endif
876 imgdecode_init_hack(Img);
877
878 rdat = Img->dat;
879 segArray = drms_array_create(DRMS_TYPE_SHORT,
880 segment->info->naxis,
881 segment->axis,
882 rdat,
883 &dstatus);
884 ImgC = Img; //set current image pointer
885 return(0);
886 }
887
888 // An fsn has changed in the context of a normal stream of
889 // tlm files. Returns 0 on success.
890 int fsn_change_normal()
891 {
892 int dstatus, rstatus, compid, n, k;
893 char reopen_dsname[256];
894 char *cptr;
895
896 printk("*FSN has changed from %u to %u\n", fsn_prev, fsnx);
897 if(fsn_prev == 0) { //startup mode. restore any prev image
898 errmsgcnt = 0;
899 fsn_prev = fsnx;
900 if(hmiaiaflg)
901 sprintf(reopen_dsname, "%s[%u]", LEV0SERIESNAMEAIA, fsnx);
902 else
903 sprintf(reopen_dsname, "%s[%u]", LEV0SERIESNAMEHMI, fsnx);
904 printk("Open normal prev ds: %s\n", reopen_dsname);
905 rset = drms_open_records(drms_env, reopen_dsname, &rstatus);
906 if(rstatus) {
907 printk("Can't do drms_open_records(%s)\n", reopen_dsname);
908 return(1); // !!!TBD
909 }
910 if(!rset || (rset->n == 0) || rstatus) {
911 printk("No prev ds\n"); // start a new image
912 fsn_normal_new_image();
913 }
914 else {
915 Img->initialized = 1;
916 Img->reopened = 1;
917 Img->fsn = fsnx;
918 Img->apid = appid;
919 rs_old = rset->records[0];
920 rs = drms_clone_record(rs_old, DRMS_PERMANENT, DRMS_COPY_SEGMENTS, &rstatus);
921 if(rstatus) {
922 printk("Can't do drms_clone_record()\n");
923 return(1); // !!!TBD ck
924 }
925 drms_close_records(rset, DRMS_FREE_RECORD);
926 rstatus = drms_setkey_int(rs, "FSN", fsnx);
927 Img->telnum = drms_getkey_int(rs, "CAMERA", &rstatus);
928 Img->telnum--;
929 Img->cropid = drms_getkey_int(rs, "CROPID", &rstatus);
930 Img->fid = drms_getkey_int(rs, "FID", &rstatus); //!!NEW 22Mar2010
931 Img->luid = drms_getkey_int(rs, "LUTID", &rstatus);
932 if(rstatus) {
933 Img->luid = 0; //!!!TEMP try this
934 printk("ERROR on getkey_int for LUTID\n");
935 }
936 Img->tap = drms_getkey_int(rs, "TAPCODE", &rstatus);
937 compid = drms_getkey_int(rs, "COMPID", &rstatus);
938 if(compid == 0) {
939 n = 16; k = 0;
940 }
941 else {
942 k = compid & 0x07; //low 3 bits
943 n = compid >> 3; //next 5 bits
944 n = n & 0x1F;
945 }
946 Img->N = n;
947 Img->K = k;
948 Img->R = drms_getkey_int(rs, "BITSELID", &rstatus);
949 Img->overflow = drms_getkey_int(rs, "OVERFLOW", &rstatus);
950 Img->headerr = drms_getkey_int(rs, "HEADRERR", &rstatus);
951 Img->totalvals = drms_getkey_int(rs, "TOTVALS", &rstatus);
952 Img->datavals = drms_getkey_int(rs, "DATAVALS", &rstatus);
953 Img->npackets = drms_getkey_int(rs, "NPACKETS", &rstatus);
954 Img->nerrors = drms_getkey_int(rs, "NERRORS", &rstatus);
955 Img->last_pix_err = drms_getkey_int(rs, "EOIERROR", &rstatus);
956
957 TIME fpt = drms_getkey_double(rs, "IMGFPT", &rstatus);
958 Img->first_packet_time = round(65536.0*(fpt - sdo_epoch));
959 if(Img->first_packet_time == 0)
960 Img->first_packet_time = UINT64_MAX; //fix for stuck 1958 value
961 snprintf(oldtlmdsnam, 128, "%s", drms_getkey_string(rs, "TLMDSNAM",&rstatus));
962 cptr = strstr(oldtlmdsnam, "VC");
963 if(cptr)
964 snprintf(tlmnamekeyfirst, 23, "%s", cptr);
965 else
966 sprintf(tlmnamekeyfirst, "%s", "UNK");
967 segment = drms_segment_lookupnum(rs, 0);
968 cArray = drms_segment_read(segment, DRMS_TYPE_SHORT, &rstatus);
969 if(rstatus) {
970 printk("Can't do drms_segment_read()\n");
971 return(1); // !!!!TBD ck
972 }
973 short *adata = (short *)cArray->data;
974 memcpy(Img->dat, adata, 2*MAXPIXELS);
975 rdat = Img->dat;
976 segArray = drms_array_create(DRMS_TYPE_SHORT,
977 segment->info->naxis,
978 segment->axis,
979 rdat,
980 &dstatus);
981 ImgC = Img; //set current image pointer
982 drms_free_array(cArray); //must free from drms_segment_read()
983 }
984 }
985 else {
986 if(rs) { // make sure have a created record
987 close_image(rs, segment, segArray, Img, fsn_prev);
988 //force a commit to DB on an image boundry & not during a rexmit
989 if(imagecnt++ >= IMAGE_NUM_COMMIT) {
990 printk("drms_server_end_transaction()\n");
991 drms_server_end_transaction(drms_env, 0 , 0);
992 printk("drms_server_begin_transaction()\n");
993 drms_server_begin_transaction(drms_env); //start another cycle
994 imagecnt = 0;
995 }
996 fileimgcnt++;
997 }
998 else {
999 printk("**ERROR: Null record ptr for an opened image fsn=%u\n",fsn_prev);
1000 }
1001 if(fsn_normal_new_image()) {
1002 printk("**ERROR: Can't create new image\n");
1003 return(1);
1004 }
1005 }
1006 return(0);
1007 }
1008
1009 // An fsn has changed in the context of a retransmitted or higher version
1010 // tlm file. Returns 0 on success.
1011 int fsn_change_rexmit()
1012 {
1013 char rexmit_dsname[256];
1014 int rstatus, dstatus, compid, n, k;
1015 char *cptr;
1016
1017 if(fsn_prev != 0) { // close image of prev fsn if not 0
1018 if(rsc) { //make sure have created record
1019 close_image(rsc, segmentc, oldArray, ImgO, fsn_prev);
1020 imagecnt++;
1021 fileimgcnt++;
1022 }
1023 else {
1024 printk("**ERROR: Null record ptr for an rexmit image fsn=%u\n",fsn_prev);
1025 }
1026 }
1027 errmsgcnt = 0;
1028 fsn_prev = fsnx;
1029 if(hmiaiaflg)
1030 sprintf(rexmit_dsname, "%s[%u]", LEV0SERIESNAMEAIA, fsnx);
1031 else
1032 sprintf(rexmit_dsname, "%s[%u]", LEV0SERIESNAMEHMI, fsnx);
1033 printk("Open prev ds: %s\n", rexmit_dsname);
1034 rset = drms_open_records(drms_env, rexmit_dsname, &rstatus);
1035 if(rstatus) {
1036 printk("Can't do drms_open_records(%s)\n", rexmit_dsname);
1037 return(1); // !!!TBD
1038 }
1039 if(!rset || (rset->n == 0) || rstatus) {
1040 startnew:
1041 printk("No prev ds\n"); // start a new image
1042 ImgO->initialized = 0;
1043 ImgO->reopened = 0;
1044 imgdecode_init_hack(ImgO);
1045 sprintf(tlmnamekeyfirst, "%s", tlmnamekey); //save for TLMDSNAM
1046 rsc = drms_create_record(drms_env, lev0seriesname, DRMS_PERMANENT, &rstatus);
1047 if(rstatus) {
1048 if(rstatus == DRMS_ERROR_SUMOPEN) {
1049 printk("**ERROR: DRMS can't open w/SUMS. Aborting...\n");
1050 abortit(4);
1051 }
1052 printk("Can't create record for %s fsn=%u\n", lev0seriesname, fsnx);
1053 return(1); // !!!TBD ck this
1054 }
1055 rstatus = drms_setkey_int(rsc, "FSN", fsnx);
1056 if(!(segmentc = drms_segment_lookup(rsc, "image"))) {
1057 printk("No drms_segment_lookup(rsc, image)\n");
1058 return(1);
1059 }
1060 rdat = ImgO->dat;
1061 oldArray = drms_array_create(DRMS_TYPE_SHORT,
1062 segmentc->info->naxis,
1063 segmentc->axis,
1064 rdat,
1065 &dstatus);
1066 }
1067 else {
1068 ImgO->initialized = 1;
1069 ImgO->reopened = 1;
1070 ImgO->fsn = fsnx;
1071 ImgO->apid = appid;
1072 rs_old = rset->records[0];
1073 rsc = drms_clone_record(rs_old, DRMS_PERMANENT, DRMS_COPY_SEGMENTS, &rstatus);
1074 if(rstatus) {
1075 printk("Can't do drms_clone_record()\n");
1076 printk("Assume this was a temp ds and the segments are now gone...\n");
1077 goto startnew;
1078 //return(1); // !!!TBD ck
1079 }
1080 drms_close_records(rset, DRMS_FREE_RECORD);
1081 rstatus = drms_setkey_int(rsc, "FSN", fsnx);
1082 ImgO->telnum = drms_getkey_int(rsc, "CAMERA", &rstatus);
1083 ImgO->telnum--;
1084 ImgO->cropid = drms_getkey_int(rsc, "CROPID", &rstatus);
1085 ImgO->fid = drms_getkey_int(rsc, "FID", &rstatus); //!!NEW 22Mar2010
1086 ImgO->luid = drms_getkey_int(rsc, "LUTID", &rstatus);
1087 ImgO->tap = drms_getkey_int(rsc, "TAPCODE", &rstatus);
1088 compid = drms_getkey_int(rsc, "COMPID", &rstatus);
1089 if(compid == 0) {
1090 n = 16; k = 0;
1091 }
1092 else {
1093 k = compid & 0x07; //low 3 bits
1094 n = compid >> 3; //next 5 bits
1095 n = n & 0x1F;
1096 }
1097 ImgO->N = n;
1098 ImgO->K = k;
1099 ImgO->R = drms_getkey_int(rsc, "BITSELID", &rstatus);
1100 ImgO->overflow = drms_getkey_int(rsc, "OVERFLOW", &rstatus);
1101 ImgO->headerr = drms_getkey_int(rsc, "HEADRERR", &rstatus);
1102 ImgO->totalvals = drms_getkey_int(rsc, "TOTVALS", &rstatus);
1103 ImgO->datavals = drms_getkey_int(rsc, "DATAVALS", &rstatus);
1104 ImgO->npackets = drms_getkey_int(rsc, "NPACKETS", &rstatus);
1105 ImgO->nerrors = drms_getkey_int(rsc, "NERRORS", &rstatus);
1106 ImgO->last_pix_err = drms_getkey_int(rsc, "EOIERROR", &rstatus);
1107
1108 TIME fpt = drms_getkey_double(rsc, "IMGFPT", &rstatus);
1109 ImgO->first_packet_time = round(65536.0*(fpt - sdo_epoch));
1110 if(ImgO->first_packet_time == 0)
1111 ImgO->first_packet_time = UINT64_MAX; //fix for stuck 1958 value
1112 snprintf(oldtlmdsnam, 128, "%s", drms_getkey_string(rsc, "TLMDSNAM",&rstatus));
1113 cptr = strstr(oldtlmdsnam, "VC");
1114 if(cptr)
1115 snprintf(tlmnamekeyfirst, 23, "%s", cptr);
1116 else
1117 sprintf(tlmnamekeyfirst, "%s", "UNK");
1118 segmentc = drms_segment_lookupnum(rsc, 0);
1119 cArray = drms_segment_read(segmentc, DRMS_TYPE_SHORT, &rstatus);
1120 if(rstatus) {
1121 printk("Can't do drms_segment_read()\n");
1122 return(1); // !!!!TBD ck
1123 }
1124 short *adata = (short *)cArray->data;
1125 memcpy(ImgO->dat, adata, 2*MAXPIXELS);
1126 rdat = ImgO->dat;
1127 oldArray = drms_array_create(DRMS_TYPE_SHORT,
1128 segmentc->info->naxis,
1129 segmentc->axis,
1130 rdat,
1131 &dstatus);
1132 drms_free_array(cArray); //must free from drms_segment_read()
1133 }
1134 ImgC = ImgO; //set current image pointer
1135 return(0);
1136 }
1137
1138 // Process the tlm file to validate and to extract the lev0 image.
1139 int get_tlm(char *file, int rexmit, int higherver)
1140 {
1141 FILE *fpin;
1142 unsigned char cbuf[PKTSZ];
1143 long long gap_42_cnt;
1144 int status, rstatus, fpkt_cnt, i, j, sync_bad_cnt;
1145 int datval, eflg, firstflg;
1146 unsigned int cnt1, cnt2, cnt3, gap_24_cnt;
1147 int zero_pn;
1148 unsigned short pksync1, pksync2;
1149 float ftmp;
1150 int decode_status=0;
1151 unsigned int Fsn;
1152
1153 if(!(fpin = fopen(file, "r"))) { // open the tlm input
1154 printk("*Can't open tlm file %s\n", file);
1155 return(1);
1156 }
1157 BeginTimer(1); //time tlm file processing
1158 printk("*Processing tlm file %s\n", file);
1159 fpkt_cnt = sync_bad_cnt = eflg = errmsgcnt = fileimgcnt = 0;
1160 zero_pn = gap_24_cnt = gap_42_cnt = 0;
1161 firstflg = 1;
1162 if(rexmit || higherver) {
1163 if(Img->initialized) { // close normal mode image
1164 if(rs) {
1165 close_image(rs, segment, segArray, Img, fsn_prev);
1166 printk("drms_server_end_transaction()\n");
1167 drms_server_end_transaction(drms_env, 0 , 0);
1168 printk("drms_server_begin_transaction()\n");
1169 drms_server_begin_transaction(drms_env); //start another cycle
1170 imagecnt = 0;
1171 }
1172 else
1173 printk("**ERROR: Null record ptr for an opened image fsn=%u\n",fsn_prev);
1174 }
1175 fsn_pre_rexmit = fsn_prev; // restore this at end of rexmit tlm file
1176 fsn_prev = 0; // cause a new image
1177 }
1178 // read a VCDU packet
1179 while((status = fread(cbuf,sizeof(char),PKTSZ,fpin) ) == PKTSZ) {
1180 pksync1 = MDI_getshort(cbuf);
1181 pksync2 = MDI_getshort(cbuf+2);
1182 if((pksync1 == 0) && (pksync2 == 0)) { // skip 0 pn code
1183 if(!zero_pn) { // give msg for 1st one only
1184 printk("*0 PN code at pkt# %d\n", fpkt_cnt);
1185 printk("*Subsequent ones will be ignored until non-0 again\n");
1186 zero_pn = 1;
1187 }
1188 fpkt_cnt++; // count # of pkts found
1189 continue;
1190 }
1191 if((pksync1 != 0x1acf) || (pksync2 != 0xfc1d)) {
1192 printk("*Lost sync at VCDU pkt# %d. pksync1=%x pksync2=%x\n",
1193 fpkt_cnt, pksync1, pksync2);
1194 fpkt_cnt++; // count # of pkts found
1195 eflg++;
1196 if(sync_bad_cnt++ > 4) {
1197 printk("**Too many out of sync packets.\n");
1198 //return(1);
1199 return(0); //changed on 01Oct2010
1200 }
1201 printk(" Will attempt to press on...\n");
1202 zero_pn = 0;
1203 continue;
1204 }
1205 if(firstflg) { // print first good sync found
1206 printk("*VCDU pkt# %d sync = %x %x\n", fpkt_cnt, pksync1, pksync2);
1207 }
1208 fpkt_cnt++; // count # of pkts found
1209 // get 24 bit VCDU counter
1210 cnt1 = MDI_getshort(cbuf+6);
1211 cnt2 = MDI_getshort(cbuf+8);
1212 cnt2 = (cnt2 >> 8)& 0xFF;
1213 cnt2 = ((cnt1 << 8)& 0xFF00) + cnt2;
1214 cnt1 = (cnt1 >> 8)& 0xFF;
1215 vcdu_24_cnt = (cnt1*65536) + cnt2;
1216 if(vcdu_24_cnt_next != vcdu_24_cnt) {
1217 printk("*VCDU 24bit seq num out of sequence. exp: %u rec: %u\n",
1218 vcdu_24_cnt_next, vcdu_24_cnt);
1219 if(vcdu_24_cnt_next > vcdu_24_cnt) {
1220 printk("*NOTE: VCDU 24 bit counter retarded\n"); //cntr does go thru 0
1221 printk("*NOTE: gap report will be inaccurate (tbd)\n");
1222 }
1223 if(!firstflg) { // don't count gap across .tlm files
1224 gap_24_cnt += vcdu_24_cnt - vcdu_24_cnt_next;
1225 }
1226 }
1227 vcdu_24_cnt_next = vcdu_24_cnt + 1;
1228 // now get the 42bit IM_PDU counter
1229 cnt1 = MDI_getshort(cbuf+10);
1230 cnt2 = MDI_getshort(cbuf+12);
1231 cnt3 = MDI_getshort(cbuf+14);
1232 cnt1 = cnt1 & 0x03ff;
1233 vcdu_seq_num = (cnt1*4294967296) + (cnt2*65536) + cnt3;
1234 // printk("vcdu_seq_num = %lld\n", vcdu_seq_num);
1235 if(vcdu_seq_num_next != vcdu_seq_num) {
1236 printk("*IM_PDU seq num out of sequence. exp: %lld rec: %lld\n",
1237 vcdu_seq_num_next, vcdu_seq_num);
1238 if(vcdu_seq_num_next > vcdu_seq_num) {
1239 printk("*NOTE: IM_PDU 42 bit counter retarded\n");
1240 printk("*NOTE: gap report will be inaccurate\n");
1241 }
1242 if(!firstflg) { // don't count gap across .tlm files
1243 gap_42_cnt += vcdu_seq_num - vcdu_seq_num_next;
1244 }
1245 eflg++;
1246 }
1247 firstflg = 0;
1248 vcdu_seq_num_next = vcdu_seq_num + 1;
1249 // get the App ID. Low 11 bit of short at buf+18
1250 appid = MDI_getshort(cbuf+18);
1251 appid = appid & 0x07ff;
1252 if(hmiaiaflg) { //aia
1253 //testid1 = 509; testid2 = 519;
1254 testid1 = 507; testid2 = 517;
1255 }
1256 else {
1257 //testid1 = 409; testid2 = 419;
1258 testid1 = 407; testid2 = 417;
1259 }
1260 //if(appid == TESTAPPID) { // appid of test pattern
1261 if((appid == testid1) || (appid == testid2)) {
1262 if(errmsgcnt++ < MAXERRMSGCNT) {
1263 printk("*Test ApID of %0x found for IM_PDU Cntr = %lld\n",
1264 appid, vcdu_seq_num);
1265 for(i=0, j=TESTVALUE; i < 877; i=i+2, j++) {
1266 datval = MDI_getshort(cbuf+32+i); // next data value
1267 if(datval != j) {
1268 printk("*Test data value=%0x, expected=%0x for IM_PDU Cntr=%lld\n",
1269 datval, j, vcdu_seq_num);
1270 printk("*File = %s\n", file);
1271 eflg++;
1272 break; // skip the rest of this packet
1273 }
1274 }
1275 }
1276 continue; // go on to next packet
1277 }
1278
1279 //printk("$$$$$ appid found = 0x%x %d\n", appid, appid); //!!TEMP
1280 // Parse tlm packet headers.
1281 if(appid == APID_HMI_SCIENCE_1 || appid == APID_HMI_SCIENCE_2 ||
1282 appid == APID_AIA_SCIENCE_1 || appid == APID_AIA_SCIENCE_2)
1283 {
1284 cnt1 = MDI_getshort(cbuf+32);
1285 cnt2 = MDI_getshort(cbuf+34);
1286 fsnx = (unsigned int)(cnt1<<16)+(unsigned int)(cnt2);
1287 fsnx = fsnx & 0x3fffffff; //low 30bits for fsn */
1288 if(fsnx == 0) continue; //a 0 fsn is not acceptable
1289 if(rexmit || higherver) {
1290 if(fsnx != fsn_prev) { // the fsn has changed
1291 if(fsn_change_rexmit()) { //handle old & new images
1292 printk("***FATAL ERROR in fsn_change_rexmit()\n");
1293 return(1);
1294 }
1295 }
1296 else { //prev could be hk w/diff apid
1297 ImgC->apid = appid;
1298 }
1299 }
1300 else { // continuing normal stream
1301 if(fsnx != fsn_prev) { // the fsn has changed
1302 if(fsn_change_normal()) { //handle old & new images
1303 printk("***FATAL ERROR in fsn_change_normal()\n");
1304 return(1);
1305 }
1306 }
1307 }
1308 // send the sci data to Keh-Cheng. call with pointer to M_PDU_Header
1309 rstatus = imgdecode((unsigned short *)(cbuf+10), ImgC);
1310 switch(rstatus) {
1311 case 0:
1312 // A science data VCDU was successfully decoded
1313 break;
1314 case IMGDECODE_DECOMPRESS_ERROR:
1315 if(errmsgcnt++ < MAXERRMSGCNT)
1316 printk("*imgdecode() ret: IMGDECODE_DECOMPRESS_ERROR\n");
1317 break;
1318 case IMGDECODE_TOO_MANY_PIXELS:
1319 if(errmsgcnt++ < MAXERRMSGCNT)
1320 printk("*imgdecode() ret: IMGDECODE_TOO_MANY_PIXELS\n");
1321 break;
1322 case IMGDECODE_BAD_N:
1323 if(errmsgcnt++ < MAXERRMSGCNT)
1324 printk("*imgdecode() ret: IMGDECODE_BAD_N\n");
1325 break;
1326 case IMGDECODE_BAD_APID:
1327 if(errmsgcnt++ < MAXERRMSGCNT)
1328 printk("*imgdecode() ret: IMGDECODE_BAD_APID\n");
1329 break;
1330 case IMGDECODE_NO_LOOKUP_TABLE:
1331 if(errmsgcnt++ < MAXERRMSGCNT)
1332 printk("*imgdecode() ret: IMGDECODE_NO_LOOKUP_TABLE\n");
1333 break;
1334 case IMGDECODE_LOOKUP_ID_MISMATCH:
1335 if(errmsgcnt++ < MAXERRMSGCNT)
1336 printk("*imgdecode() ret: IMGDECODE_LOOKUP_ID_MISMATCH\n");
1337 break;
1338 case IMGDECODE_BAD_LOOKUP_TABLE:
1339 if(errmsgcnt++ < MAXERRMSGCNT)
1340 printk("*imgdecode() ret: IMGDECODE_BAD_LOOKUP_TABLE\n");
1341 break;
1342 case IMGDECODE_NO_CROP_TABLE:
1343 if(errmsgcnt++ < MAXERRMSGCNT)
1344 printk("*imgdecode() ret: IMGDECODE_NO_CROP_TABLE\n");
1345 break;
1346 case IMGDECODE_CROP_ID_MISMATCH:
1347 if(errmsgcnt++ < MAXERRMSGCNT)
1348 printk("*imgdecode() ret: IMGDECODE_CROP_ID_MISMATCH\n");
1349 break;
1350 case IMGDECODE_BAD_CROP_GEOMETRY:
1351 if(errmsgcnt++ < MAXERRMSGCNT)
1352 printk("*imgdecode() ret: IMGDECODE_BAD_CROP_GEOMETRY\n");
1353 break;
1354 case IMGDECODE_BAD_CROP_TABLE:
1355 if(errmsgcnt++ < MAXERRMSGCNT)
1356 printk("*imgdecode() ret: IMGDECODE_BAD_CROP_TABLE\n");
1357 break;
1358 case IMGDECODE_BAD_CROP_SKIP_TAKE:
1359 if(errmsgcnt++ < MAXERRMSGCNT)
1360 printk("*imgdecode() ret: IMGDECODE_BAD_CROP_SKIP_TAKE\n");
1361 break;
1362 case IMGDECODE_BAD_OFFSET:
1363 if(errmsgcnt++ < MAXERRMSGCNT)
1364 printk("*imgdecode() ret: IMGDECODE_BAD_OFFSET\n");
1365 break;
1366 case IMGDECODE_OUT_OF_MEMORY:
1367 if(errmsgcnt++ < MAXERRMSGCNT)
1368 printk("*imgdecode() ret: IMGDECODE_OUT_OF_MEMORY\n");
1369 break;
1370 default:
1371 if(errmsgcnt++ < MAXERRMSGCNT)
1372 printk("*imgdecode() ret: unknown err status = %d:\n", rstatus);
1373 break;
1374 }
1375 }
1376 else { // send the HK data to Carl
1377 //printk("$$$ appid assumed hk = 0x%x %d\n", appid, appid); //!!TEMP
1378 decode_status = decode_next_hk_vcdu((unsigned short *)(cbuf+10), &Hk, &Fsn);
1379 switch (decode_status) {
1380 case SUCCESS_HK_NEED_TO_WTD_CTD:
1381 printk("*ISP found for fsn = %u\n", Fsn);
1382 fsnx = Fsn;
1383 if(rexmit || higherver) {
1384 if(fsnx != fsn_prev) { // the fsn has changed
1385 if(fsn_change_rexmit()) { //handle old & new images
1386 printk("***FATAL ERROR in fsn_change_rexmit()\n");
1387 return(1);
1388 }
1389 }
1390 //calculate and setkey some values from the keywords returned
1391 HMI_compute_exposure_times(rsc, Hk->keywords, hmiaiaflg);
1392 whk_status = write_hk_to_drms(rsc, &Hk); //ISP keywords to drms
1393 if(!hmiaiaflg) {
1394 if(whk_status = set_HMI_mech_values(rsc)) {
1395 printk("***ERROR: mechanism position keywords are wrong!\n");
1396 }
1397 }
1398 }
1399 else { //normal stream
1400 if(fsnx != fsn_prev) { // the fsn has changed
1401 if(fsn_change_normal()) { //handle old & new images
1402 printk("***FATAL ERROR in fsn_change_normal()\n");
1403 return(1);
1404 }
1405 }
1406 //calculate and setkey some values from the keywords returned
1407 HMI_compute_exposure_times(rs, Hk->keywords, hmiaiaflg);
1408 whk_status = write_hk_to_drms(rs, &Hk); //ISP keywords to drms
1409 if(!hmiaiaflg) {
1410 if(whk_status = set_HMI_mech_values(rs)) {
1411 printk("***ERROR: mechanism position keywords are wrong!\n");
1412 }
1413 }
1414 }
1415 hk_ccsds_free(&Hk);
1416 rstatus=0;
1417 break;
1418 case SUCCESS_HK_NEED_TO_CTD:
1419 /*NO need to write keywords's to drms for level0 data series
1420 BUT need to commit to drms for level0 by APID data series*/
1421 break;
1422 case SUCCESS_SKIP_IMAGE:
1423 printk("decode_next_hk_vcdu() ret:Warning:SUCCESS_SKIP_IMAGE\n");
1424 break;
1425 case SUCCESS_SKIP_PROCESSING_APID:
1426 printk("decode_next_hk_vcdu() ret:Warning:SUCCESS_SKIP_PROCESSING_APID:\n");
1427 break;
1428 case ERROR_HK_FAILED_GETTING_FSN:
1429 printk("decode_next_hk_vcdu() ret:Warning:ERROR_HK_FAILED_GETTING_FSN:\n");
1430 break;
1431 case ERROR_NODATA:
1432 printk("decode_next_hk_vcdu() ret:Warning:ERROR_NODATA\n");
1433 break;
1434 case ERROR_HK_ENVIRONMENT_VARS_NOT_SET:
1435 printk("decode_next_hk_vcdu() ret:ERROR:ERROR_HK_ENVIRONMENT_VARS_NOT_SET\n");
1436 break;
1437 case ERROR_HK_FAILED_OPEN_DAYFILE:
1438 printk("decode_next_hk_vcdu() ret:ERROR:ERROR_HK_FAILED_OPEN_DAYFILE\n");
1439 break;
1440 default:
1441 printk("decode_next_hk_vcdu() ret:Warning:Unexpected return code for decode_status:<%d>:\n", decode_status);
1442 break;
1443 }
1444
1445 }
1446 } // end of rd of vcdu pkts
1447 fclose(fpin);
1448 if(!eflg) {
1449 printk("*No errors in tlm file\n");
1450 }
1451 if(rexmit || higherver) { // close the opened record
1452 if(rsc) { // make sure have created record
1453 close_image(rsc, segmentc, oldArray, ImgO, fsnx);
1454 printk("drms_server_end_transaction()\n"); //commit at end of file
1455 drms_server_end_transaction(drms_env, 0 , 0);
1456 printk("drms_server_begin_transaction()\n\n");
1457 drms_server_begin_transaction(drms_env); //start another cycle
1458 imagecnt = 0;
1459 fileimgcnt++;
1460 //fsn_prev = fsn_pre_rexmit; // restore orig for next normal .tlm file
1461 fsn_prev = 0; //need for restart of normal mode
1462 rsc = 0;
1463 }
1464 }
1465 ftmp = EndTimer(1);
1466 printk("**Processed %s\n**with %d images and %d VCDUs in %f sec\n\n",
1467 file, fileimgcnt, fpkt_cnt, ftmp);
1468
1469 //now commit to DB in case another file doesn't come in
1470 /***************************TEMP***********************************
1471 NOTE: Can't do this unless close current image and then set fsn=0
1472 so that the next tlm file will start by opening the image again.
1473 I don't think that we want this. Instead find a way to get the ^C
1474 instead of DRMS, and then do a close and commit.
1475 printk("drms_server_end_transaction()\n");
1476 drms_server_end_transaction(drms_env, 0 , 0);
1477 printk("drms_server_begin_transaction()\n\n");
1478 drms_server_begin_transaction(drms_env); //start another cycle
1479 imagecnt = 0;
1480 ***************************TEMP***********************************/
1481
1482 if(fpkt_cnt != total_tlm_vcdu) {
1483 printk("**WARNING: Found #vcdu=%d; expected=%d\n", fpkt_cnt, total_tlm_vcdu);
1484 }
1485 //if(gap_24_cnt != total_missing_vcdu) {
1486 // printk("**WARNING: VCDU 24bit cntr gaps=%d; expected=%d\n",
1487 // gap_24_cnt, total_missing_vcdu);
1488 //}
1489 if(gap_42_cnt != total_missing_im_pdu) {
1490 printk("**WARNING: IM_PDU 42bit cntr gaps=%lld; expected=%lld\n",
1491 gap_42_cnt, total_missing_im_pdu);
1492 }
1493 ignoresigalrmflg = 1; //got a file. noop next alarm signal timeout
1494 return(0);
1495 }
1496
1497 // This is the main loop that gets the .qac and .tlm files and
1498 // puts them into ds tlmseriesname and extracts the lev0 and puts it in
1499 // lev0seriesname in DRMS.
1500 void do_ingest()
1501 {
1502 FILE *fp;
1503 DRMS_Record_t *rs_tlm;
1504 DIR *dfd;
1505 NAMESORT *nameptr;
1506 struct dirent *dp;
1507 int i, j, status, mvstat;
1508 int rexmit, higherversion;
1509 char path[DRMS_MAXPATHLEN];
1510 char name[128], line[128], tlmfile[128], tlmname[96];
1511 char cmd[256], xxname[128], vername[16];
1512 char *token, *filename;
1513
1514 if((dfd=opendir(tlmdir)) == NULL) {
1515 printk("**Can't opendir(%s) to find files\n", tlmdir);
1516 abortit(3);
1517 }
1518 i = 0;
1519 if((nameptr = (NAMESORT *)malloc(MAXFILES * sizeof(NAMESORT))) == NULL) {
1520 printk("***Can't alloc memory for file name sort\n");
1521 abortit(3);
1522 }
1523
1524 while((dp=readdir(dfd)) != NULL) {
1525 // printk("%s\n", dp->d_name) ; continue; // !!TEMP
1526 // Only accept our files.
1527 if(strstr(dp->d_name, pchan) || strstr(dp->d_name, rchan) || strstr(dp->d_name, ".dsf")) {
1528 nameptr[i++].name = strdup(dp->d_name);
1529 if(i >= MAXFILES) {
1530 printk("***Fatal error. Too many (%d) files in %s\n", MAXFILES, tlmdir);
1531 printf("***Fatal error. Too many (%d) files in %s\n", MAXFILES, tlmdir);
1532 abortit(3);
1533 }
1534 if(!strstr(dp->d_name, ".dsf")) cntsleeps = 0; //we saw a file
1535 }
1536 }
1537 closedir(dfd);
1538 qsort(nameptr, i, sizeof(NAMESORT), &compare_names);
1539
1540 for(j=0; j < i; j++) {
1541 //printk("####QSORT FILES: %s\n", nameptr[j].name); // !!TEMP
1542 // NOTE: the dsf files is moved to indir/dsf e.g. (/dds/soc2pipe/aia/dsf)
1543 // Currently the cron job pipefe_rm does this:
1544 // `/bin/mv $dsfname /dds/socdc/hmi/dsf`
1545 //Only do for V01/VC02. VC04/VC05 won't mv the .dsf
1546 if(!strcmp(pchan, "VC01") || !strcmp(pchan, "VC02")) {
1547 if(strstr(nameptr[j].name, ".dsf")) {
1548 //sprintf(cmd, "/bin/mv %s/%s %s", tlmdir, nameptr[j].name, outdir);
1549 sprintf(cmd, "/bin/mv -f %s/%s %s/dsf/",tlmdir,nameptr[j].name,tlmdir);
1550 printk("*mv dsf file to %s/dsf/\n", tlmdir);
1551 printk("%s\n", cmd);
1552 if(system(cmd)) {
1553 printk("***Error on: %s\n", cmd);
1554 }
1555 }
1556 }
1557 if(!strstr(nameptr[j].name, ".qac")) { // can be .qac or .qacx
1558 free(nameptr[j].name);
1559 continue;
1560 }
1561 rexmit = higherversion = 0;
1562 if(strstr(nameptr[j].name, ".qacx")) { // this is a rexmit file
1563 rexmit = 1;
1564 }
1565 sprintf(name, "%s/%s", tlmdir, nameptr[j].name);
1566 printk("%s\n*Found qac file:\n* %s\n", do_datestr(), name);
1567 if(!(fp=fopen(name, "r"))) {
1568 printk("***Can't open %s\n", name);
1569 free(nameptr[j].name);
1570 continue;
1571 }
1572 // NOTE: the qac file is already verified by the caller of ingest_lev0
1573 while(fgets(line, 256, fp)) { // get qac file lines
1574 if(line[0] == '#' || line[0] == '\n') continue;
1575 if(strstr(line, "TLM_FILE_NAME=")) {
1576 token = (char *)strtok(line, "=");
1577 token = (char *)strtok(NULL, "\n");
1578 printk("tlm file is %s\n", token);
1579 sprintf(tlmfile, "%s/%s", tlmdir, token);
1580 sprintf(tlmname, "%s", token);
1581 }
1582 else if(strstr(line, "TLM_FILE_SIZE=")) {
1583 token = (char *)strtok(line, "=");
1584 token = (char *)strtok(NULL, "=");
1585 printk("*tlm file size is %s", token);
1586 }
1587 else if((strstr(line, "TOTAL_TLM_IM_PDU=")) || (strstr(line, "TOTAL_VCDU="))) {
1588 token = (char *)strtok(line, "=");
1589 token = (char *)strtok(NULL, "\n");
1590 total_tlm_vcdu = atoi(token);
1591 }
1592 else if(strstr(line, "TOTAL_MISSING_VCDU=")) {
1593 token = (char *)strtok(line, "=");
1594 token = (char *)strtok(NULL, "\n");
1595 total_missing_vcdu = atoi(token);
1596 }
1597 else if(strstr(line, "TOTAL_MISSING_IM_PDU=")) {
1598 token = (char *)strtok(line, "=");
1599 token = (char *)strtok(NULL, "\n");
1600 total_missing_im_pdu = atol(token);
1601 break;
1602 }
1603 }
1604 fclose(fp);
1605 //alarm(ALRMSEC); //restart alarm if no more files come
1606 strcpy((char *)tlmnamekey, (char *)tlmname);
1607 filename = (char *)rindex(tlmname, '.');
1608 if(!filename) {
1609 printk("**ERROR: Bad formed tlm name in qac file\n");
1610 printk(" tlm name = %s\n", tlmname);
1611 continue;
1612 }
1613 *filename = 0; // elim .tlm
1614 *((char *)tlmnamekey+22) = 0; // elim after hh_mm_ss
1615 rs_tlm = drms_create_record(drms_env, tlmseriesname,
1616 DRMS_PERMANENT, &status);
1617 if(status) {
1618 if(status == DRMS_ERROR_SUMOPEN) {
1619 printk("**ERROR: DRMS can't open w/SUMS. Aborting...\n");
1620 abortit(4);
1621 }
1622 printk("***Can't create record for %s. Status=%d\n", tlmseriesname, status);
1623 continue;
1624 }
1625 if((status = drms_setkey_string(rs_tlm, "filename", tlmnamekey))) {
1626 printk("**ERROR: drms_setkey_string failed for 'filename'\n");
1627 }
1628 drms_record_directory(rs_tlm, path, 0);
1629 if(!*path) {
1630 printk("***ERROR: No path to segment for %s\n", tlmseriesname);
1631 continue;
1632 }
1633 if(outdir) {
1634 sprintf(cmd, "cp -p %s %s", name, outdir);
1635 printk("*cp qac file to %s\n", outdir);
1636 printk("%s\n", cmd);
1637 if(system(cmd)) {
1638 printk("***Error on: %s\n", cmd);
1639 }
1640 sprintf(cmd, "cp -p %s %s", tlmfile, outdir);
1641 printk("*cp tlm file to %s\n", outdir);
1642 printk("%s\n", cmd);
1643 if(system(cmd)) {
1644 printk("***Error on: %s\n", cmd);
1645 }
1646 }
1647 sprintf(cmd, "/bin/mv %s %s", name, path);
1648 printk("*mv qac to %s\n", path);
1649 printk("%s\n", cmd);
1650 if(status = system(cmd)) {
1651 printk("**ERROR: %d errno=%d on: %s\n", status, errno, cmd);
1652 if(WIFEXITED(status)) {
1653 if(mvstat = WEXITSTATUS(status)) { //status ret by mv
1654 printk("**ERROR: mv exit status = %d\n", mvstat);
1655 }
1656 }
1657 }
1658 sprintf(cmd, "/bin/mv %s %s", tlmfile, path);
1659 printk("*mv tlm to %s\n", path);
1660 printk("%s\n", cmd);
1661 if(status = system(cmd)) {
1662 printk("**ERROR: %d errno=%d on: %s\n", status, errno, cmd);
1663 if(WIFEXITED(status)) {
1664 if(mvstat = WEXITSTATUS(status)) { //status ret by mv
1665 printk("**ERROR: mv exit status = %d\n", mvstat);
1666 }
1667 }
1668 printk("**Continue after ERROR on mv of tlm file\n");
1669 continue;
1670 }
1671 if((status = drms_close_record(rs_tlm, DRMS_INSERT_RECORD))) {
1672 printk("**ERROR: drms_close_record failed for %s\n", tlmseriesname);
1673 }
1674
1675 sprintf(xxname, "%s/%s.tlm", path, tlmname);
1676 filename = (char *)rindex(tlmname, '_');
1677 sprintf(vername, "%s", filename); // e.g. _00 or _01 etc.
1678 if(strcmp(vername, "_00")) { // this is a higher vers # file
1679 higherversion = 1;
1680 printk("Higher version tlm found: %s.tlm\n", tlmname);
1681 }
1682 firstfound = 1; //a file has been seen
1683 if(get_tlm(xxname, rexmit, higherversion)) { // lev0 extraction of image
1684 printk("***Error in lev0 extraction for %s\n", xxname);
1685 //printk("***Going to abort\n");
1686 //abortflg = 1;
1687 }
1688 if((stat(stopfile, &stbuf) == 0) || abortflg) { break; } //signal to stop
1689 }
1690 free(nameptr);
1691 }
1692
1693 // Initial setup stuff called when main is first entered.
1694 void setup()
1695 {
1696 FILE *fp;
1697 int i;
1698 char string[128], cwdbuf[128], idstr[256];
1699 char envfile[100], s1[256],s2[256],s3[256], line[256];
1700 ThreadSigErr_t error = kThreadSigErr_Success;
1701
1702 sdo_epoch = sscan_time("1958.01.01_00:00:00_TAI");
1703 do_datestr();
1704 printk_set(h0log, h0log); // set for printk calls
1705 printk("%s\n", datestr);
1706 getcwd(cwdbuf, 126);
1707 sprintf(idstr, "Cwd: %s\nCall: ", cwdbuf);
1708 if(grounddata)
1709 sprintf(string, "ingest_lev0 -g started as pid=%d user=%s\n", getpid(), username);
1710 else
1711 sprintf(string, "ingest_lev0 started as pid=%d user=%s\n", getpid(), username);
1712 strcat(idstr, string);
1713 printk("*%s", idstr);
1714 if(restartflg) printk("-r ");
1715 sprintf(argvc, "vc=%s", vc);
1716 sprintf(argindir, "indir=%s", tlmdir);
1717 sprintf(arglogfile, "logfile=%s", logname);
1718 if(outdir) {
1719 sprintf(argoutdir, "outdir=%s", outdir);
1720 printk("%s %s %s %s\n", argvc, argindir, argoutdir, arglogfile);
1721 } else {
1722 printk("%s %s %s\n", argvc, argindir, arglogfile);
1723 }
1724 strcpy(pchan, vc); // virtual channel primary
1725 if(rexmitmode) //new 'stopX' 11/2/2012
1726 sprintf(stopfile, "/usr/local/logs/lev0/%s_stopX", pchan);
1727 else
1728 sprintf(stopfile, "/usr/local/logs/lev0/%s_stop", pchan);
1729 //Dont rm stopfile any more (1/6/2012).
1730 //With the new rexmit dir there is a second
1731 //ingest_lev0 running on a VC and it needs the stop file too.
1732 //The stop file is removed when ingest_lev0 is started by
1733 //doingestlev0_[HMI,AIA].pl
1734 //sprintf(string, "/bin/rm -f %s", stopfile); //remove any stop file
1735 //system(string);
1736 for(i=0; ; i++) { // ck for valid and get redundant chan
1737 if(!strcmp(p_r_chan_pairs[i].pchan, pchan)) {
1738 strcpy(rchan, p_r_chan_pairs[i].rchan);
1739 hmiaiaflg = p_r_chan_pairs[i].instru;
1740 break;
1741 }
1742 if(!strcmp(p_r_chan_pairs[i].pchan, "n/a")) {
1743 printk("!!ERROR: Invalid VCid (%s) specified\n", pchan);
1744 fprintf(stderr, "!!ERROR: Invalid VCid (%s) specified. Abort\n", pchan);
1745 abortit(1);
1746 }
1747 }
1748 if(hmiaiaflg) {
1749 if(grounddata) {
1750 sprintf(tlmseriesname, "%s", TLMSERIESNAMEAIAGND);
1751 sprintf(lev0seriesname, "%s", LEV0SERIESNAMEAIAGND);
1752 }
1753 else {
1754 sprintf(tlmseriesname, "%s", TLMSERIESNAMEAIA);
1755 sprintf(lev0seriesname, "%s", LEV0SERIESNAMEAIA);
1756 }
1757 }
1758 else {
1759 if(grounddata) {
1760 sprintf(tlmseriesname, "%s", TLMSERIESNAMEHMIGND);
1761 sprintf(lev0seriesname, "%s", LEV0SERIESNAMEHMIGND);
1762 }
1763 else {
1764 sprintf(tlmseriesname, "%s", TLMSERIESNAMEHMI);
1765 sprintf(lev0seriesname, "%s", LEV0SERIESNAMEHMI);
1766 }
1767 }
1768 if(!restartflg) {
1769 printk("tlmseriesname=%s\nlev0seriesname=%s\n",
1770 tlmseriesname, lev0seriesname);
1771 }
1772 sprintf(bld_vers, "%s", jsoc_version);
1773 umask(002); // allow group write
1774 Image.initialized = 0; // init the two image structures
1775 ImageOld.initialized = 0;
1776 Img = &Image;
1777 ImgO = &ImageOld;
1778 imgdecode_init_hack(Img);
1779 imgdecode_init_hack(ImgO);
1780
1781 //set environment variables for hk code
1782 //create filename and path
1783 if(grounddata) strcpy(envfile, ENVFILE_GND );
1784 else strcpy(envfile, ENVFILE );
1785 //fopen file
1786 if(!(fp=fopen(envfile, "r"))) {
1787 printk("***Can't open %s. Check setting is correct\n", envfile);
1788 exit(0);
1789 }
1790 //read in lines
1791 while( fgets(line, MAXLINE_IN_FILE, fp) != NULL )
1792 {
1793 if (!strncmp(line, "#", 1)) {
1794 continue; /*skip comments */
1795 }
1796 else {
1797 sscanf(line, "%s %s %s ", s1,s2,s3);
1798 // set each line to setenv();
1799 setenv(s2, s3, 1);
1800 }
1801 }
1802 fclose(fp);
1803
1804 /***************************!!TBD ck this out later*************************
1805 //setup a sigalrm for threads
1806 //pthread_mutex_init(&mutex, NULL);
1807
1808 // Set alarm
1809 gettimeofday(&tv0, NULL);
1810 if (td_createalarm(ALRMSEC, shandler, &mutex, &talarm)) { //to shandler in ALRMSEC
1811 pthread_mutex_destroy(&mutex);
1812 printk("Can't set an alarm signal for %dsec of no data\n", ALRMSEC);
1813 }
1814 *****************************************************************************/
1815 }
1816
1817 // Module main function.
1818 int DoIt(void)
1819 {
1820 pid_t pid;
1821 int wflg = 1;
1822 char *args[6];
1823 char callcmd[256];
1824
1825 if (nice_intro())
1826 return (0);
1827 if(!(username = (char *)getenv("USER"))) username = "nouser";
1828 vc = cmdparams_get_str(&cmdparams, "vc", NULL);
1829 tlmdir = cmdparams_get_str(&cmdparams, "indir", NULL);
1830 outdir = cmdparams_get_str(&cmdparams, "outdir", NULL);
1831 logfile = cmdparams_get_str(&cmdparams, "logfile", NULL);
1832 if(strstr(tlmdir, "rexmit")) { rexmitmode = 1; }
1833 if (strcmp(vc, NOTSPECIFIED) == 0) {
1834 fprintf(stderr, "'vc' virt channel must be specified. Abort\n");
1835 return(1);
1836 }
1837 if (strcmp(tlmdir, NOTSPECIFIED) == 0) {
1838 fprintf(stderr, "'indir' must be specified. Abort\n");
1839 return(1);
1840 }
1841 if (strcmp(outdir, NOTSPECIFIED) == 0) {
1842 outdir = NULL;
1843 }
1844 if (strcmp(logfile, NOTSPECIFIED) == 0) {
1845 sprintf(logname, H0LOGFILE, username, vc, gettimetag());
1846 }
1847 else {
1848 sprintf(logname, "%s", logfile);
1849 }
1850 if(restartflg) {
1851 //sleep(30); //make sure old ingest_lev0 is done
1852 if((h0logfp=fopen(logname, "a")) == NULL)
1853 fprintf(stderr, "**Can't open for append the log file %s\n", logname);
1854 }
1855 else {
1856 if((h0logfp=fopen(logname, "w")) == NULL)
1857 fprintf(stderr, "**Can't open the log file %s\n", logname);
1858 }
1859 setup();
1860 while(wflg) {
1861 do_ingest(); // loop to get files from the input dir
1862 /************************NOOP this out for now********************************
1863 if(sigalrmflg) { // process an alarm timout for no data in
1864 sigalrmflg = 0;
1865 td_destroyalarm(&talarm, &mutex);
1866 gettimeofday(&tv0, NULL);
1867 if (td_createalarm(ALRMSEC, shandler, &mutex, &talarm)) {
1868 pthread_mutex_destroy(&mutex);
1869 printk("Can't set an alarm signal for %dsec of no data\n", ALRMSEC);
1870 }
1871 if(!ignoresigalrmflg && firstfound) {
1872 if(Image.initialized) {
1873 if(rs && fsn_prev) { //make sure have a created record
1874 close_image(rs, segment, segArray, &Image, fsn_prev);
1875 printk("*Closed image on timeout FSN=%u\n", fsn_prev);
1876 }
1877 }
1878 else {
1879 printk("*No image to close on timeout\n");
1880 }
1881 printk("alrm_sig: drms_server_end_transaction()\n");
1882 drms_server_end_transaction(drms_env, 0 , 0); //commit
1883 printk("alrm_sig: drms_server_begin_transaction()\n");
1884 drms_server_begin_transaction(drms_env); //start another cycle
1885 fsn_prev = 0; //make sure don't try to flush this image
1886 imagecnt = 0; //and start a new transaction interval
1887 }
1888 ignoresigalrmflg = 0;
1889 }
1890 *****************************************************************************/
1891
1892 if((stat(stopfile, &stbuf) == 0) || abortflg) {
1893 printk("Abort or Found file: %s. Terminate.\n", stopfile);
1894 if(abortflg) send_mail("Abort for ingest_lev0 for %s\n", pchan);
1895 //now close any open image
1896 if(Image.initialized) {
1897 if(rs) { //make sure have a created record
1898 close_image(rs, segment, segArray, &Image, fsn_prev);
1899 }
1900 }
1901 else {
1902 printk("*No image to close on exit\n");
1903 }
1904 //No need to commit here. the exit will do it
1905 //printk("restart: drms_server_end_transaction()\n");
1906 //drms_server_end_transaction(drms_env, 0 , 0); //commit
1907 //NEW 1Jun2010: leave the stopfile.
1908 //Must use doingestlev0_HMI(AIA).pl to start ingest_lev0
1909 //sprintf(callcmd, "/bin/rm -f %s", stopfile);
1910 //system(callcmd);
1911 if(rexmitmode) //new 11/02/21012
1912 sprintf(callcmd, "touch /usr/local/logs/lev0/%s_exitX", pchan);
1913 else
1914 sprintf(callcmd, "touch /usr/local/logs/lev0/%s_exit", pchan);
1915 system(callcmd); //let the world know we're gone
1916 wflg = 0; //leave DoIt()
1917 continue;
1918 }
1919 sleep(sleep_interval); //normally 2 sec
1920 if(cntsleeps == 0) { //file was seen
1921 if(paused) { //send resume data flow msg
1922 paused = 0;
1923 if(!rexmitmode) {
1924 send_mail("tlm files seen again for ingest_lev0 for %s\n", pchan);
1925 }
1926 }
1927 }
1928 cntsleeps++; //#of 2sec sleeps w/o any files in do_ingest()
1929 if(cntsleeps > 300) { // >600sec w/o any files
1930 if(!paused) {
1931 if(!rexmitmode) {
1932 send_mail("No files seen for ingest_lev0 for %s for 600sec\n", pchan);
1933 }
1934 paused = 1;
1935 }
1936 }
1937 }
1938 /*************!!TBD noop this out for now
1939 td_destroyalarm(&talarm);
1940 //pthread_mutex_destroy(&mutex); //can't destroy here. used in shandler()
1941 pthread_mutex_destroy(&mutex); //if don't detroy here can end up w/2 ingest_lev0
1942 //on a restart by doingestlev0.pl ??
1943 ***************************************************/
1944 return(0);
1945 }
1946