ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/lev0/apps/ingest_lev0_hmiaia.c
Revision: 1.4
Committed: Thu Sep 5 22:21:10 2013 UTC (10 years ago) by prodtest
Content type: text/plain
Branch: MAIN
CVS Tags: Ver_8-8, Ver_8-11, Ver_8-2, Ver_8-10, Ver_8-1, Ver_8-6, Ver_LATEST, Ver_8-4, Ver_9-41, Ver_8-3, Ver_8-5, Ver_8-12, Ver_8-7, Ver_9-5, Ver_9-4, Ver_9-3, Ver_9-2, Ver_9-1, Ver_9-0, HEAD
Changes since 1.3: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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