File indexing completed on 2024-09-08 03:28:59
0001 /* 0002 SPDX-FileCopyrightText: 2008 Akarsh Simha <akarshsimha@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 // Program to convert star data stored in a MySQL database into 0008 // the binary file format used by KStars 0009 0010 #define DB_TBL "nomad" 0011 #define DB_DB "stardb" 0012 #define VERBOSE 1 0013 #define HTM_LEVEL 6 0014 #define NTRIXELS 32768 // TODO: Change if HTM Level Changes 0015 #define INDEX_ENTRY_SIZE 12 0016 #define MYSQL_STARS_PER_QUERY 1000000 0017 0018 #include "binfile.h" 0019 0020 #include <mysql/mysql.h> 0021 #include <sys/types.h> 0022 #include <stdlib.h> 0023 #include <stdio.h> 0024 #include <math.h> 0025 #include <string.h> 0026 0027 /* 0028 * struct to store star data, to be written in this format, into the binary file. 0029 */ 0030 0031 typedef struct deepStarData 0032 { 0033 int32_t RA; 0034 int32_t Dec; 0035 int16_t dRA; 0036 int16_t dDec; 0037 int16_t B; 0038 int16_t V; 0039 } deepStarData; 0040 0041 /* 0042 * Dump the data file header. 0043 * 0044 * WARNING: Must edit every time the definition of the deepStarData structures changes 0045 * 0046 * f : Data file handle 0047 */ 0048 0049 int writeDataFileHeader(FILE *f) 0050 { 0051 char ASCII_text[124]; 0052 u_int16_t nfields; 0053 u_int32_t nindexes; 0054 int16_t endian_id = 0x4B53; 0055 u_int8_t version_no = 1; 0056 0057 if (f == NULL) 0058 return 0; 0059 0060 nfields = 6; 0061 0062 str2charv(ASCII_text, "KStars Star Data v1.0. To be read using the 32-bit starData structure only.", 124); 0063 fwrite(ASCII_text, 124, 1, f); 0064 fwrite(&endian_id, 2, 1, f); 0065 fwrite(&version_no, 1, 1, f); 0066 fwrite(&nfields, sizeof(u_int16_t), 1, f); 0067 0068 writeDataElementDescription(f, "RA", 4, DT_INT32, 1000000); 0069 writeDataElementDescription(f, "Dec", 4, DT_INT32, 100000); 0070 writeDataElementDescription(f, "dRA", 2, DT_INT16, 10); 0071 writeDataElementDescription(f, "dDec", 2, DT_INT16, 10); 0072 writeDataElementDescription(f, "B", 2, DT_INT16, 100); 0073 writeDataElementDescription(f, "V", 2, DT_INT16, 100); 0074 0075 nindexes = NTRIXELS; 0076 fwrite(&nindexes, sizeof(u_int32_t), 1, f); 0077 0078 return 1; 0079 } 0080 0081 int main(int argc, char *argv[]) 0082 { 0083 /* === Declarations === */ 0084 0085 int ret, i, exitflag; 0086 long int lim; 0087 0088 double Mag; 0089 0090 unsigned long us_header_offset; 0091 unsigned long usf_trix_begin; 0092 unsigned long usf_trix_count; 0093 unsigned long ntrixels; 0094 int16_t maglim; 0095 u_int8_t htm_level; 0096 u_int16_t MSpT_unnamed; 0097 0098 char query[512]; 0099 u_int32_t current_trixel; 0100 0101 /* File streams */ 0102 FILE *f; /* Pointer to "current" file */ 0103 FILE *usf; /* Handle to star data file */ 0104 FILE *usfhead; /* Handle to star header file */ 0105 0106 /* deepStarData structure */ 0107 deepStarData data; 0108 0109 /* MySQL structures */ 0110 MYSQL link; 0111 MYSQL_RES *result; 0112 MYSQL_ROW row; 0113 0114 /* Check the number of arguments */ 0115 if (argc <= 6) 0116 { 0117 fprintf(stderr, "USAGE %s DBUserName DBPassword DeepStarDataFile DeepStarHeaderFile DBName [TableName]\n", 0118 argv[0]); 0119 fprintf(stderr, "The database used is a MySQL DB on localhost. The default table name is `nomad`\n"); 0120 } 0121 0122 /* == Open all file streams required == */ 0123 /* Unnamed Star Handling */ 0124 usf = fopen(argv[3], "wb"); 0125 if (usf == NULL) 0126 { 0127 fprintf(stderr, "ERROR: Could not open %s [Deep Star Data File] for binary write.\n", argv[3]); 0128 return 1; 0129 } 0130 0131 usfhead = fopen(argv[4], "wb"); 0132 if (usfhead == NULL) 0133 { 0134 fprintf(stderr, "ERROR: Could not open %s [Deep Star Header File] for binary write.\n", argv[4]); 0135 fcloseall(); 0136 return 1; 0137 } 0138 0139 /* MySQL connect */ 0140 if (mysql_init(&link) == NULL) 0141 { 0142 fprintf(stderr, "ERROR: Failed to initialize MySQL connection!\n"); 0143 return 1; 0144 } 0145 0146 ret = mysql_real_connect(&link, "localhost", argv[1], argv[2], argv[5], 0, NULL, 0); 0147 0148 if (!ret) 0149 { 0150 fprintf(stderr, "ERROR: MySQL connect failed for the following reason: %s\n", mysql_error(&link)); 0151 fcloseall(); 0152 return 1; 0153 } 0154 0155 if (mysql_select_db(&link, argv[5])) 0156 { 0157 fprintf(stderr, "ERROR: Could not select MySQL database %s. MySQL said: %s", argv[5], mysql_error(&link)); 0158 fcloseall(); 0159 mysql_close(&link); 0160 return 1; 0161 } 0162 0163 if (VERBOSE) 0164 fprintf(stdout, "Size of deepStarData structure: %d\n", sizeof(deepStarData)); 0165 0166 /* Write file headers */ 0167 writeDataFileHeader(usfhead); 0168 us_header_offset = ftell(usfhead); 0169 0170 /* Leave space for / write a deep magnitude limit specification in the data files */ 0171 maglim = (int)(-5.0 * 100); 0172 fwrite(&maglim, 2, 1, usf); // Bogus entry 0173 0174 /* Write a HTM level specification in the data file */ 0175 htm_level = HTM_LEVEL; 0176 fwrite(&htm_level, 1, 1, usf); 0177 0178 /* Leave space for a specification of MSpT (Maximum Stars per Trixel) in the data files */ 0179 MSpT_unnamed = 0; 0180 fwrite(&MSpT_unnamed, 2, 1, usf); // Bogus entry 0181 0182 /* Initialize some variables */ 0183 lim = 0; 0184 exitflag = 0; 0185 current_trixel = 0; 0186 usf_trix_count = 0; 0187 usf_trix_begin = 0188 2 + 1 + 0189 2; // The 2 + 1 + 2 is to leave space for deep magnitude limit, HTM Level and MSpT specification. TODO: Change this if things change. 0190 ntrixels = 0; 0191 0192 /* Recurse over every MYSQL_STARS_PER_QUERY DB entries */ 0193 while (!exitflag) 0194 { 0195 /* Build MySQL query for next MYSQL_STARS_PER_QUERY stars */ 0196 sprintf(query, 0197 "SELECT `Trixel`, `RA`, `Dec`, `dRA`, `dDec`, `B`, `V`, `UID` FROM `%s` ORDER BY `trixel`, `Mag` ASC " 0198 "LIMIT %ld, %d", 0199 (argc >= 7) ? argv[6] : DB_TBL, lim, MYSQL_STARS_PER_QUERY); 0200 0201 if (VERBOSE) 0202 { 0203 fprintf(stderr, "SQL Query: %s\n", query); 0204 } 0205 0206 /* Execute MySQL query and get the result */ 0207 mysql_real_query(&link, query, (unsigned int)strlen(query)); 0208 result = mysql_use_result(&link); 0209 0210 if (!result) 0211 { 0212 fprintf(stderr, "MySQL returned NULL result: %s\n", mysql_error(&link)); 0213 fcloseall(); 0214 mysql_close(&link); 0215 return 1; 0216 } 0217 0218 exitflag = -1; 0219 0220 /* Process the result row by row */ 0221 while (row = mysql_fetch_row(result)) 0222 { 0223 /* Very verbose details */ 0224 if (VERBOSE > 1) 0225 { 0226 fprintf(stderr, "UID = %s\n", row[12]); 0227 for (i = 0; i <= 14; ++i) 0228 fprintf(stderr, "\tField #%d = %s\n", i, row[i]); 0229 } 0230 0231 if (exitflag == -1) 0232 exitflag = 0; 0233 0234 /* Write index entries if we've changed trixel */ 0235 u_int32_t new_trixel = atoi(row[0]); 0236 if (current_trixel != new_trixel) 0237 { 0238 if (VERBOSE) 0239 { 0240 fprintf(stderr, "Trixel Changed from %d to %s = %d!\n", current_trixel, row[0], new_trixel); 0241 } 0242 while (new_trixel != current_trixel) 0243 { 0244 writeIndexEntry(usfhead, current_trixel, 0245 us_header_offset + NTRIXELS * INDEX_ENTRY_SIZE + usf_trix_begin, usf_trix_count); 0246 usf_trix_begin = ftell(usf); 0247 if (usf_trix_count > MSpT_unnamed) 0248 MSpT_unnamed = usf_trix_count; 0249 current_trixel++; 0250 ntrixels++; 0251 usf_trix_count = 0; 0252 if (VERBOSE) 0253 { 0254 fprintf(stderr, "%d %d\n", current_trixel - 1, ntrixels); 0255 } 0256 } 0257 if (VERBOSE) 0258 { 0259 fprintf(stderr, "Done writing trixel entry\n"); 0260 } 0261 } 0262 0263 /* Initializations */ 0264 0265 usf_trix_count++; 0266 f = usf; 0267 0268 /* Convert various fields and make entries into the deepStarData structure */ 0269 str2int32(&data.RA, row[1], 6); 0270 str2int32(&data.Dec, row[2], 5); 0271 str2int16(&data.dRA, row[3], 3); 0272 str2int16(&data.dDec, row[4], 3); 0273 str2int16(&data.B, row[5], 3); 0274 str2int16(&data.V, row[6], 3); 0275 0276 int16_t B = data.B; 0277 int16_t V = data.V; 0278 0279 if (V == 30000) 0280 { 0281 if (B - 1600 > maglim && B != 30000) 0282 { 0283 maglim = B - 1600; 0284 } 0285 } 0286 else 0287 { 0288 if (V > maglim) 0289 { 0290 maglim = V; 0291 } 0292 } 0293 0294 /* Write the data into the appropriate data file and any names into the name file */ 0295 if (VERBOSE) 0296 fprintf(stderr, "Writing UID = %s...", row[7]); 0297 fwrite(&data, sizeof(deepStarData), 1, f); 0298 if (VERBOSE) 0299 fprintf(stderr, "Done.\n"); 0300 } 0301 mysql_free_result(result); 0302 lim += MYSQL_STARS_PER_QUERY; 0303 } 0304 0305 do 0306 { 0307 writeIndexEntry(usfhead, current_trixel, us_header_offset + NTRIXELS * INDEX_ENTRY_SIZE + usf_trix_begin, 0308 usf_trix_count); 0309 usf_trix_begin = ftell(usf); 0310 usf_trix_count = 0; 0311 current_trixel++; 0312 ntrixels++; 0313 } while (current_trixel != NTRIXELS); 0314 0315 if (ntrixels != NTRIXELS) 0316 { 0317 fprintf(stderr, 0318 "ERROR: Expected %u trixels, but found %u instead. Please redefine NTRIXELS in this program, or check " 0319 "the source database for bogus trixels\n", 0320 NTRIXELS, ntrixels); 0321 } 0322 0323 rewind(usf); 0324 fwrite(&maglim, 2, 1, usf); 0325 fwrite(&htm_level, 1, 1, usf); 0326 fwrite(&MSpT_unnamed, 2, 1, usf); 0327 0328 fcloseall(); 0329 mysql_close(&link); 0330 0331 return 0; 0332 }