2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) any later version.
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) 2008 Liam Girdwood
19 #define _GNU_SOURCE /* for strtof and NAN */
29 #include <libastrodb/db.h>
30 #include <libastrodb/astro.h>
31 #include <libastrodb/table.h>
32 #include <libastrodb/adbstdio.h>
34 #define FILE_NAME_SIZE 256
35 #define FLOAT_SIZE '6' /* CDS F size and below for a float else double */
36 #define IMPORT_LINE_SIZE 1024
39 * libastrodb interface version
41 #define ADB_IDX_VERSION 2
43 /*! \fn static int insert_posn_mag (void* d, void* object)
44 * \brief Insert object into dataset based upon position and mag
46 static int insert_posn_mag(void *d
, void *object
)
48 int ra
, dec
, mag
, offset
;
49 struct astrodb_table
*table
= (struct astrodb_table
*) d
;
50 struct astrodb_object_deep
*dobject
= object
;
52 if (dobject
->posn
.ra
< table
->db
->ra_min
||
53 dobject
->posn
.ra
> table
->db
->ra_max
)
55 if (dobject
->posn
.dec
< table
->db
->dec_min
||
56 dobject
->posn
.dec
> table
->db
->dec_max
)
58 if (dobject
->Vmag
> table
->db
->mag_faint
||
59 dobject
->Vmag
< table
->db
->mag_bright
)
62 ra
= ((int) dobject
->posn
.ra
- table
->db
->ra_min
) /
63 table
->ra_stride_size
;
64 dec
= ((int) dobject
->posn
.dec
- table
->db
->dec_min
) /
65 table
->dec_stride_size
;
66 mag
= ((int) dobject
->Vmag
- table
->db
->mag_bright
) /
67 table
->mag_stride_size
;
69 if ((offset
= table_calc_deep_offset(table
, ra
, dec
, mag
)) < 0)
72 *(table
->objects
+ offset
) =
73 astrodb_slist_prepend(*(table
->objects
+ offset
), object
);
74 (table
->status
+ offset
)->flags
= ADB_SMEM
;
75 (table
->status
+ offset
)->size
++;
79 /*! \fn static int insert_posn_type (void* d, void* object)
80 * \brief Insert object into dataset based upon position and type
82 static int insert_posn_type(void *d
, void *object
)
84 int ra
, dec
, type
, offset
;
85 struct astrodb_table
*table
= (struct astrodb_table
*) d
;
86 struct astrodb_object_deep
*dobject
= object
;
88 if (dobject
->posn
.ra
< table
->db
->ra_min
||
89 dobject
->posn
.ra
> table
->db
->ra_max
)
91 if (dobject
->posn
.dec
< table
->db
->dec_min
||
92 dobject
->posn
.dec
> table
->db
->dec_max
)
94 if (dobject
->Vmag
> table
->db
->mag_faint
||
95 dobject
->Vmag
< table
->db
->mag_bright
)
98 ra
= ((int) dobject
->posn
.ra
- table
->db
->ra_min
) /
99 table
->ra_stride_size
;
100 dec
= ((int) dobject
->posn
.dec
- table
->db
->dec_min
) /
101 table
->dec_stride_size
;
102 type
= (int) dobject
->aobject
.oclass
;
104 if ((offset
= table_calc_deep_offset(table
, ra
, dec
, type
)) < 0)
107 *(table
->objects
+ offset
) =
108 astrodb_slist_prepend(*(table
->objects
+ offset
), object
);
109 (table
->status
+ offset
)->flags
= ADB_SMEM
;
110 (table
->status
+ offset
)->size
++;
114 /*! \fn static int insert_hash_id (void* d, void* object)
115 * \brief Insert object into dataset based upon position and mag
117 static int insert_hash_id(void *d
, void *object
)
119 struct astrodb_table
*table
= (struct astrodb_table
*) d
;
120 int offset
= table_calc_hash(((struct astrodb_object
*) object
)->id
,
121 OBJECT_ID_SIZE
, table
->no_tiles
);
123 *(table
->objects
+ offset
) =
124 astrodb_slist_prepend(*(table
->objects
+ offset
), object
);
125 (table
->status
+ offset
)->flags
= ADB_SMEM
;
126 (table
->status
+ offset
)->size
++;
130 /*! \fn static inline int insert_hash_id_hobject(astrodb_table *table, void *object, int hid)
131 * \brief Insert object into dataset based upon position and mag
133 static inline int insert_hash_id_hobject(struct astrodb_table
*table
,
134 void *object
, int hid
)
138 offset
= table_calc_hash((char *) object
+ table
->hmaps
[hid
].offset
,
139 OBJECT_ID_SIZE
, table
->no_tiles
);
141 *(table
->hmaps
[hid
].hobjects
+ offset
) =
142 astrodb_slist_prepend(*(table
->hmaps
[hid
].hobjects
+ offset
), object
);
146 /*! \fn static int insert_posn_mag_hash (void* d, void* object)
147 * \brief Insert object into dataset based upon position and mag
149 static int insert_posn_mag_hash(void *d
, void *object
)
151 int ra
, dec
, mag
, offset
;
152 struct astrodb_table
*table
= (struct astrodb_table
*) d
;
153 struct astrodb_object_deep
*dobject
= object
;
156 if (dobject
->posn
.ra
< table
->db
->ra_min
||
157 dobject
->posn
.ra
> table
->db
->ra_max
)
159 if (dobject
->posn
.dec
< table
->db
->dec_min
||
160 dobject
->posn
.dec
> table
->db
->dec_max
)
162 if (dobject
->Vmag
> table
->db
->mag_faint
||
163 dobject
->Vmag
< table
->db
->mag_bright
)
166 ra
= ((int) dobject
->posn
.ra
- table
->db
->ra_min
) /
167 table
->ra_stride_size
;
168 dec
= ((int) dobject
->posn
.dec
- table
->db
->dec_min
) /
169 table
->dec_stride_size
;
170 mag
= ((int) dobject
->Vmag
- table
->db
->mag_bright
) /
171 table
->mag_stride_size
;
173 offset
= table_calc_deep_offset(table
, ra
, dec
, mag
);
175 astrodb_error("failed to calculate deep offset for RA %3.2f"
176 " DEC %3.2f mag %3.2f\n", ra
, dec
, mag
);
180 *(table
->objects
+ offset
) =
181 astrodb_slist_prepend(*(table
->objects
+ offset
), object
);
182 (table
->status
+ offset
)->flags
= ADB_SMEM
;
183 (table
->status
+ offset
)->size
++;
185 for (i
= 0; i
< table
->num_hmaps
; i
++)
186 insert_hash_id_hobject(table
, object
, i
);
191 /*! \fn static int insert_posn_type_hash (void* d, void* object)
192 * \brief Insert object into dataset based upon position and type
194 static int insert_posn_type_hash(void *d
, void *object
)
196 int ra
, dec
, type
, offset
, i
;
197 struct astrodb_table
*table
= (struct astrodb_table
*) d
;
198 struct astrodb_object_deep
*dobject
= object
;
200 if (dobject
->posn
.ra
< table
->db
->ra_min
||
201 dobject
->posn
.ra
> table
->db
->ra_max
)
203 if (dobject
->posn
.dec
< table
->db
->dec_min
||
204 dobject
->posn
.dec
> table
->db
->dec_max
)
206 if (dobject
->Vmag
> table
->db
->mag_faint
||
207 dobject
->Vmag
< table
->db
->mag_bright
)
210 ra
= ((int) dobject
->posn
.ra
- table
->db
->ra_min
) /
211 table
->ra_stride_size
;
212 dec
= ((int) dobject
->posn
.dec
- table
->db
->dec_min
) /
213 table
->dec_stride_size
;
214 type
= (int) dobject
->aobject
.oclass
;
215 if ((offset
= table_calc_deep_offset(table
, ra
, dec
, type
)) < 0)
218 *(table
->objects
+ offset
) =
219 astrodb_slist_prepend(*(table
->objects
+ offset
), object
);
220 (table
->status
+ offset
)->flags
= ADB_SMEM
;
221 (table
->status
+ offset
)->size
++;
223 for (i
= 0; i
< table
->num_hmaps
; i
++)
224 insert_hash_id_hobject(table
, object
, i
);
235 * Table containing dataset insertion funcs and ID's
237 struct _insert table_insert
[] = {
238 {insert_posn_mag
, INSERT_POSN_MAG
},
239 {insert_posn_type
, INSERT_POSN_TYPE
},
240 {insert_hash_id
, INSERT_HASH_ID
},
241 {insert_posn_mag_hash
, INSERT_POSN_MAG_HASH
},
242 {insert_posn_type_hash
, INSERT_POSN_TYPE_HASH
},
245 void table_set_insert(struct astrodb_table
*table
, int id
)
249 for (i
= 0; i
< astrodb_size(table_insert
); i
++) {
250 if (id
== table_insert
[i
].id
) {
251 table
->object_insert
= table_insert
[i
].func
;
255 table
->object_insert
= NULL
;
258 /* table type insert's */
259 static int int_insert(void *dest
, void *src
)
263 *(int *) dest
= strtol(src
, &ptr
, 10);
268 static int float_insert(void *dest
, void *src
)
272 *(float *) dest
= strtof(src
, &ptr
);
274 *(float*) dest
= FP_NAN
;
279 static int double_insert(void *dest
, void *src
)
283 *(double *) dest
= strtod(src
, &ptr
);
285 *(double*) dest
= FP_NAN
;
290 static int str_insert(void *dest
, void *src
)
296 static int double_dms_mins(void *dest
, void *src
)
300 *(double *) dest
+= strtod(src
, &ptr
) / 60.0;
305 static int double_dms_secs(void *dest
, void *src
)
309 *(double *) dest
+= strtod(src
, &ptr
) / 3600.0;
314 static int sign_insert(void *dest
, void *src
)
316 if (*(char*)src
== '-')
317 *(double *) dest
*= -1.0;
320 static int double_hms_hrs(void *dest
, void *src
)
324 *(double *) dest
= strtod(src
, &ptr
) * 15.0;
329 static int double_hms_mins(void *dest
, void *src
)
333 *(double *) dest
+= strtod(src
, &ptr
) * 15.0 / 60.0;
338 static int double_hms_secs(void *dest
, void *src
)
342 *(double *) dest
+= strtod(src
, &ptr
) * 15.0 / 3600.0;
348 static int float_alt_insert(void *dest
, void *src
, void *src2
)
352 *(float *) dest
= strtof(src
, &ptr
);
354 /* is primary source invalid then try alternate source */
356 *(float *) dest
= strtof(src2
, &ptr
);
358 *(float*) dest
= FP_NAN
;
365 static int double_alt_insert(void *dest
, void *src
, void *src2
)
369 *(double *) dest
= strtod(src
, &ptr
);
371 /* is primary source invalid then try alternate source */
373 *(double *) dest
= strtod(src2
, &ptr
);
375 *(double *) dest
= FP_NAN
;
382 /*! \fn astrodb_ctype table_get_ctype(char *type)
383 * \brief Get C type from ASCII type
385 astrodb_ctype
table_get_ctype(char *type
)
392 if (*(type
+ 1) > FLOAT_SIZE
)
400 /*! \fn int table_get_csize(char *type)
401 * \brief Get C size from ASCII size
403 int table_get_csize(char *type
)
408 return strtol(type
+ 1, NULL
, 10);
410 if (*(type
+ 1) > FLOAT_SIZE
)
411 return sizeof(double);
413 return sizeof(float);
418 /*! \fn void *table_get_custom_insert(char *type)
419 * Get dataset type insert
421 void *table_get_custom_insert(char *type
)
424 return (void *) int_insert
;
426 return (void *) str_insert
;
428 if (*(type
+ 1) > FLOAT_SIZE
)
429 return (void *) double_insert
;
431 return (void *) float_insert
;
436 /*! \fn void *table_get_key_insert(astrodb_ctype type)
437 * Get dataset type insert
439 void *table_get_key_insert(astrodb_ctype type
)
442 case CT_DOUBLE_DMS_DEGS
:
444 return double_insert
;
451 case CT_DOUBLE_DMS_MINS
:
452 return double_dms_mins
;
453 case CT_DOUBLE_DMS_SECS
:
454 return double_dms_secs
;
460 case CT_DOUBLE_HMS_HRS
:
461 return double_hms_hrs
;
462 case CT_DOUBLE_HMS_MINS
:
463 return double_hms_mins
;
464 case CT_DOUBLE_HMS_SECS
:
465 return double_hms_secs
;
467 astrodb_error("Invalid column insert %d\n", type
);
471 /*! \fn void *table_get_alt_key_insert(astrodb_ctype type)
472 * Get dataset type insert
474 void *table_get_alt_key_insert(astrodb_ctype type
)
478 return double_alt_insert
;
480 return float_alt_insert
;
483 case CT_DOUBLE_DMS_DEGS
:
484 case CT_DOUBLE_DMS_MINS
:
485 case CT_DOUBLE_DMS_SECS
:
489 case CT_DOUBLE_HMS_HRS
:
490 case CT_DOUBLE_HMS_MINS
:
491 case CT_DOUBLE_HMS_SECS
:
492 astrodb_error("Invalid alt column insert %d\n", type
);
498 /*! \fn void table_get_object_insert(astrodb_table * table)
499 * \brief Get object insert func for table
500 * \todo index on position ans type/class
502 void table_get_object_insert(struct astrodb_table
*table
)
504 if (table_is_field(table
, "RA") &&
505 table_is_field(table
, "DEC") &&
506 table_is_field(table
, "Vmag")) {
508 if (table
->num_hmaps
) {
509 astrodb_info("Table Sectioned on Position, Magnitude and"
511 table_set_insert(table
, INSERT_POSN_MAG_HASH
);
513 astrodb_info("Table Sectioned on Position, Magnitude\n");
514 table_set_insert(table
, INSERT_POSN_MAG
);
519 if (table_is_field(table
, "RAh") &&
520 table_is_field(table
, "DEd") &&
521 table_is_field(table
, "Vmag")) {
523 if (table
->num_hmaps
) {
524 astrodb_info("Table Sectioned on Position, Magnitude and"
526 table_set_insert(table
, INSERT_POSN_MAG_HASH
);
528 astrodb_info("Table Sectioned on Position, Magnitude\n");
529 table_set_insert(table
, INSERT_POSN_MAG
);
534 astrodb_info("Indexing on ID\n");
535 table_set_insert(table
, INSERT_HASH_ID
);
538 #define INSERT_BUFFER_SIZE 128
540 static int import_data(struct astrodb_table
*table
, FILE *f
)
542 int i
, j
, count
= 0, short_records
= 0, insert
, warn
;
544 char buf
[INSERT_BUFFER_SIZE
];
549 line
= malloc(IMPORT_LINE_SIZE
);
553 astrodb_info("Starting import with object size %d bytes\n",
556 size
= table
->record_size
+ 10;
557 for (j
= 0; j
< table
->table_size
; j
++) {
559 object
= malloc(table
->object_size
);
560 if (object
== NULL
) {
564 bzero(object
, table
->object_size
);
565 bzero(line
, IMPORT_LINE_SIZE
);
567 /* try and read a little extra padding */
568 rsize
= getline(&line
, &size
, f
);
570 if (rsize
< table
->record_size
)
573 /* create row by inserting column (field) data */
574 for (i
= 0; i
< table
->object_fields
; i
++) {
575 bzero(buf
, INSERT_BUFFER_SIZE
);
576 strncpy(buf
, line
+ table
->idx
[i
].l_offset
,
577 table
->idx
[i
].l_size
);
578 insert
= table
->idx
[i
].
579 insert(object
+ table
->idx
[i
].s_offset
, buf
);
581 astrodb_warn(" blank field %s\n",
582 table
->idx
[i
].symbol
);
588 astrodb_warn("At line %d :-\n", count
);
589 astrodb_warn("line %s\n\n", line
);
592 /* insert row into table */
593 count
+= table
->object_insert(table
, object
);
595 astrodb_info("Got %d short records\n", short_records
);
596 astrodb_info("Imported %d records\n", count
);
601 static int import_data_alt(struct astrodb_table
*table
, FILE *f
)
603 int i
, j
, k
, count
= 0, short_records
= 0, warn
, insert
;
605 char buf
[INSERT_BUFFER_SIZE
], buf2
[INSERT_BUFFER_SIZE
];
610 line
= malloc(IMPORT_LINE_SIZE
);
614 astrodb_info("Starting import with object size %d bytes\n",
616 astrodb_info("Importing %d alt fields\n", table
->alt_fields
);
618 size
= table
->record_size
+ 10;
619 for (j
= 0; j
< table
->table_size
; j
++) {
620 object
= calloc(1, table
->object_size
);
621 if (object
== NULL
) {
626 bzero(object
, table
->object_size
);
627 bzero(line
, IMPORT_LINE_SIZE
);
629 /* try and read a little extra padding */
630 rsize
= getline(&line
, &size
, f
);
632 if (rsize
< table
->record_size
)
635 /* create row by inserting colunm (field) data */
636 for (i
= 0; i
< table
->object_fields
; i
++) {
637 bzero(buf
, INSERT_BUFFER_SIZE
);
638 strncpy(buf
, line
+ table
->idx
[i
].l_offset
,
639 table
->idx
[i
].l_size
);
640 insert
= table
->idx
[i
].insert(
641 object
+ table
->idx
[i
].s_offset
, buf
);
643 astrodb_warn(" blank field %s\n",
644 table
->idx
[i
].symbol
);
649 /* complete row by inserting alt column (field) data */
650 for (k
= 0; k
< table
->alt_fields
; k
++) {
651 bzero(buf
, INSERT_BUFFER_SIZE
);
652 bzero(buf2
, INSERT_BUFFER_SIZE
);
653 strncpy(buf
, line
+ table
->alt_idx
[k
].pri
.l_offset
,
654 table
->alt_idx
[k
].pri
.l_size
);
655 strncpy(buf2
, line
+ table
->alt_idx
[k
].sec
.l_offset
,
656 table
->alt_idx
[k
].sec
.l_size
);
657 insert
= table
->alt_idx
[k
].insert(object
+
658 table
->alt_idx
[k
].pri
.s_offset
,
661 astrodb_warn(" blank fields %s %s\n",
662 table
->alt_idx
[k
].pri
.symbol
,
663 table
->alt_idx
[k
].sec
.symbol
);
669 astrodb_warn("At line %d :-\n", count
);
670 astrodb_warn("line %s\n\n", line
);
673 /* insert row into table */
674 count
+= table
->object_insert(table
, object
);
676 astrodb_info("Got %d short records\n", short_records
);
677 astrodb_info("Imported %d records\n", count
);
682 /*! \fn int table_import(astrodb_table * table, char *file, astrodb_progress progress)
683 * \brief Import an ASCII dataset into table tile array
685 int table_import(struct astrodb_table
*table
, char *file
)
689 if (!table
->object_insert
) {
690 astrodb_error("Invalid object insert\n");
694 f
= fopen(file
, "r");
696 astrodb_error("failed to open file %s\n", file
);
700 table_order_index(table
);
702 if (table
->alt_fields
)
703 import_data_alt(table
, f
);
705 import_data(table
, f
);