You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1218 lines
35 KiB
1218 lines
35 KiB
/***************************************************************************
|
|
* map_loadsave.c
|
|
*
|
|
* Thu Jul 19 19:00:10 2007
|
|
* Copyright 2007 Steffen Pohle
|
|
* steffen@gulpe.de
|
|
****************************************************************************/
|
|
|
|
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_LOCALE_H
|
|
#include <locale.h>
|
|
#endif
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <dirent.h>
|
|
|
|
#include "map.h"
|
|
#include "system.h"
|
|
#include "memoryleak.h"
|
|
#include "osmroute.h"
|
|
|
|
#define MAP_BITS_SUBID 8
|
|
|
|
char *lsrw_data = NULL;
|
|
int lsrw_data_size = 0;
|
|
char *lshash_data = NULL;
|
|
int lshash_data_size = 0;
|
|
|
|
|
|
/*******************************************************************
|
|
* create filename out of the ilon and ilat field.
|
|
*/
|
|
void map_ls_get_filename_only (char *fn, int len, int ilon, int ilat) {
|
|
int flon, flat;
|
|
|
|
flon = ilon/MAP_LSHASHFACTOR;
|
|
flat = ilat/MAP_LSHASHFACTOR;
|
|
|
|
#ifdef HAVE_LOCALE_H
|
|
setlocale(LC_ALL, "C");
|
|
snprintf (fn, len, "mlon%dlat%d.mapdata", flon, flat);
|
|
setlocale(LC_ALL, NULL);
|
|
#else
|
|
snprintf (fn, len, "mlon%dlat%d.mapdata", flon, flat);
|
|
#endif
|
|
};
|
|
|
|
void map_ls_get_filename (char *fn, int len, int ilon, int ilat) {
|
|
int flon, flat;
|
|
|
|
flon = ilon/MAP_LSHASHFACTOR;
|
|
flat = ilat/MAP_LSHASHFACTOR;
|
|
|
|
#ifdef HAVE_LOCALE_H
|
|
setlocale(LC_ALL, "C");
|
|
snprintf (fn, len, "%smlon%dlat%d.mapdata", cfg.mappath, flon, flat);
|
|
setlocale(LC_ALL, NULL);
|
|
#else
|
|
snprintf (fn, len, "%smlon%dlat%d.mapdata", cfg.mappath, flon, flat);
|
|
#endif
|
|
};
|
|
|
|
|
|
/******************************************************************
|
|
* fine the stats inside the hash block, if not just load the file
|
|
* into the memory.
|
|
*/
|
|
struct map_lsstat *map_ls_statget (char *fname) {
|
|
int i, j;
|
|
struct map_lsstat *mlssptr = NULL;
|
|
struct map_lsstat mlss;
|
|
|
|
/* check inside the mlsstat block */
|
|
for (i = 0; i < MAP_LSSTAT_MAX; i++) {
|
|
if (strncmp (fname, mlsstat[i].fname, LEN_FILENAME) == 0) {
|
|
/* found in list, push it to the first entry, free whats left */
|
|
if (i > 0) {
|
|
mlss = mlsstat[i];
|
|
for (j = i; j > 0; j--)
|
|
mlsstat[j] = mlsstat[j-1];
|
|
mlsstat[0] = mlss;
|
|
}
|
|
mlssptr = mlsstat;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* if not, load file from disk */
|
|
if (mlssptr == NULL) {
|
|
mlssptr = map_ls_statopen (fname);
|
|
/* free last element in mlsstat */
|
|
if (mlsstat[MAP_LSSTAT_MAX-1].fname[0] != '\0')
|
|
map_ls_statclose (&mlsstat[MAP_LSSTAT_MAX-1]);
|
|
|
|
/* push to the first entry */
|
|
for (j = MAP_LSSTAT_MAX-1; j > 0; j--)
|
|
mlsstat[j] = mlsstat[j-1];
|
|
mlsstat[0] = *mlssptr;
|
|
mlssptr = mlsstat;
|
|
}
|
|
|
|
return mlssptr;
|
|
};
|
|
|
|
|
|
/******************************************************************
|
|
* check if we have enought free data in rw_data buffer
|
|
*/
|
|
void map_ls_rwdatacheck (int size) {
|
|
char *old;
|
|
|
|
if (lsrw_data == NULL) {
|
|
lsrw_data_size = size;
|
|
lsrw_data = ml_malloc (lsrw_data_size);
|
|
ml_addinfo (lsrw_data, "lsrw_data");
|
|
}
|
|
else if (lsrw_data_size < size) {
|
|
old = lsrw_data;
|
|
ml_addinfo (old, "old lsrw_data");
|
|
|
|
lsrw_data = ml_malloc (size);
|
|
ml_addinfo (old, "lsrw_data new");
|
|
if (old) memcpy (lsrw_data, old, lsrw_data_size);
|
|
lsrw_data_size = size;
|
|
ml_free (old);
|
|
}
|
|
else if (size == 0) {
|
|
ml_free (lsrw_data);
|
|
lsrw_data = NULL;
|
|
lsrw_data_size = 0;
|
|
}
|
|
};
|
|
|
|
|
|
void map_ls_rwdatacheckpos (int size, char **oldpos) {
|
|
int i;
|
|
|
|
i = *oldpos-lsrw_data;
|
|
map_ls_rwdatacheck (size);
|
|
*oldpos = lsrw_data+i;
|
|
};
|
|
|
|
|
|
void map_ls_hashdatacheck (int size) {
|
|
char *old;
|
|
|
|
if (lshash_data == NULL) {
|
|
lshash_data_size = size;
|
|
lshash_data = ml_malloc (lshash_data_size);
|
|
ml_addinfo (lshash_data, "lshash_data");
|
|
}
|
|
else if (lshash_data_size < size) {
|
|
old = lshash_data;
|
|
ml_addinfo (old, "old lshash_data");
|
|
|
|
lshash_data = ml_malloc (size);
|
|
ml_addinfo (lshash_data, "lshash_data new");
|
|
if (old) memcpy (lshash_data, old, lshash_data_size);
|
|
lshash_data_size = size;
|
|
ml_free (old);
|
|
}
|
|
};
|
|
|
|
|
|
void map_ls_hashdatacheckpos (int size, char **oldpos) {
|
|
int i;
|
|
|
|
i = *oldpos-lshash_data;
|
|
map_ls_hashdatacheck (size);
|
|
*oldpos = lshash_data+i;
|
|
};
|
|
|
|
|
|
/*********************************************************************
|
|
* try to open a map file, load imortant data into the mlss structure
|
|
* and return it
|
|
*/
|
|
struct map_lsstat *map_ls_statopen (char *fname) {
|
|
static struct map_lsstat mlss;
|
|
int i;
|
|
char *pos;
|
|
|
|
map_ls_rwdatacheck (12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
|
|
/* clear mlss */
|
|
strncpy (mlss.fname, fname, LEN_FILENAME);
|
|
mlss.fnametmp[0] = '\0';
|
|
for (i = 0; i < MAP_LSHASHFACTOR*MAP_LSHASHFACTOR; i++) {
|
|
mlss.r_lshpos[i].pos = 0;
|
|
mlss.r_lshpos[i].size = 0;
|
|
mlss.w_lshpos[i].pos = 0;
|
|
mlss.w_lshpos[i].size = 0;
|
|
if (i < MAP_LSFREECNT) {
|
|
mlss.w_free[i].pos = 0;
|
|
mlss.w_free[i].size = 0;
|
|
}
|
|
}
|
|
mlss.r_fd = mlss.w_fd = 0;
|
|
mlss.changed = 0;
|
|
|
|
if (file_exist (mlss.fname) == 0) {
|
|
d_printf ("map_ls_statopen file '%s' not found.", mlss.fname);
|
|
mlss.r_fd = 0;
|
|
return &mlss;
|
|
}
|
|
|
|
#if defined(__MINGW32CE__) || defined(_WIN32_WCE) || defined(__MINGW32__)
|
|
mlss.r_fd = open (mlss.fname, O_RDWR | _O_BINARY);
|
|
if (mlss.r_fd == -1) {
|
|
int error = GetLastError();
|
|
|
|
d_printf ("map_ls_statopen open file '%s'. ERROR (GetLastError): %d", mlss.fname, error);
|
|
mlss.r_fd = 0;
|
|
return &mlss;
|
|
}
|
|
#else
|
|
mlss.r_fd = open (mlss.fname, O_RDWR);
|
|
if (mlss.r_fd == -1) {
|
|
d_printf ("map_ls_statopen open file '%s'. ERROR (errno): %d:%s", mlss.fname, errno, strerror(errno));
|
|
mlss.r_fd = 0;
|
|
return &mlss;
|
|
}
|
|
#endif
|
|
// else d_printf ("map_ls_statopen open file '%s'. OK fd:%d", mlss.fname, mlss.r_fd);
|
|
|
|
read (mlss.r_fd, lsrw_data, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
pos = lsrw_data;
|
|
for (i = 0; i < MAP_LSHASHFACTOR*MAP_LSHASHFACTOR; i++) {
|
|
pos = mempop (pos, &mlss.r_lshpos[i].pos, 8);
|
|
pos = mempop (pos, &mlss.r_lshpos[i].size, 4);
|
|
}
|
|
|
|
for (i = 0; i < MAP_LSFREECNT; i++) {
|
|
pos = mempop (pos, &mlss.w_free[i].pos, 8);
|
|
pos = mempop (pos, &mlss.w_free[i].size, 4);
|
|
}
|
|
|
|
return &mlss;
|
|
};
|
|
|
|
|
|
/*********************************************************************
|
|
* close the read and write file but save first the w_free, r_lshpos
|
|
* and the w_lshpos arrays
|
|
*/
|
|
void map_ls_statclose (struct map_lsstat *lsstat) {
|
|
char *pos;
|
|
int i;
|
|
|
|
// d_printf ("map_ls_statclose called with: %p changed: %d r_fd: %d w_fd: %d", lsstat, lsstat->changed, lsstat->r_fd, lsstat->w_fd);
|
|
if (lsstat->r_fd) {
|
|
if (lsstat->changed) {
|
|
map_ls_rwdatacheck (12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
/* data changed so need to save, all filenames should be right
|
|
* so we only take care about r_fd and w_fd */
|
|
if (lsstat->w_fd == 0) {
|
|
pos = lsrw_data;
|
|
for (i = 0; i < MAP_LSHASHFACTOR*MAP_LSHASHFACTOR; i++) {
|
|
pos = mempush (pos, &lsstat->r_lshpos[i].pos, 8);
|
|
pos = mempush (pos, &lsstat->r_lshpos[i].size, 4);
|
|
}
|
|
for (i = 0; i < MAP_LSFREECNT; i++) {
|
|
pos = mempush (pos, &lsstat->w_free[i].pos, 8);
|
|
pos = mempush (pos, &lsstat->w_free[i].size, 4);
|
|
}
|
|
|
|
if (lseek (lsstat->r_fd, 0, SEEK_SET) < 0)
|
|
d_printf ("%s:%d error with lseek.", __FILE__, __LINE__);
|
|
write (lsstat->r_fd, lsrw_data, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
}
|
|
else {
|
|
/* need to copy all unchanged data into the new file */
|
|
for (i = 0; i < MAP_LSHASHFACTOR*MAP_LSHASHFACTOR; i++) {
|
|
if (lsstat->w_lshpos[i].pos == 0 && lsstat->r_lshpos[i].pos != 0) {
|
|
/* read data */
|
|
map_ls_rwdatacheck (lsstat->r_lshpos[i].size);
|
|
if (lseek (lsstat->r_fd, lsstat->r_lshpos[i].pos, SEEK_SET) < 0)
|
|
d_printf ("%s:%d error with lseek.", __FILE__, __LINE__);
|
|
read (lsstat->r_fd, lsrw_data, lsstat->r_lshpos[i].size);
|
|
|
|
/* write data */
|
|
if ((lsstat->w_lshpos[i].pos = lseek (lsstat->w_fd, 0, SEEK_END)) < 0)
|
|
d_printf ("%s:%d error with lseek.", __FILE__, __LINE__);
|
|
|
|
lsstat->w_lshpos[i].size = lsstat->r_lshpos[i].size;
|
|
write (lsstat->w_fd, lsrw_data, lsstat->w_lshpos[i].size);
|
|
}
|
|
}
|
|
|
|
pos = lsrw_data;
|
|
for (i = 0; i < MAP_LSHASHFACTOR*MAP_LSHASHFACTOR; i++) {
|
|
pos = mempush (pos, &lsstat->w_lshpos[i].pos, 8);
|
|
pos = mempush (pos, &lsstat->w_lshpos[i].size, 4);
|
|
}
|
|
for (i = 0; i < MAP_LSFREECNT; i++) {
|
|
pos = mempush (pos, &lsstat->w_free[i].pos, 8);
|
|
pos = mempush (pos, &lsstat->w_free[i].size, 4);
|
|
}
|
|
|
|
if (lseek (lsstat->w_fd, 0, SEEK_SET) < 0)
|
|
d_printf ("%s:%d error with lseek.", __FILE__, __LINE__);
|
|
write (lsstat->w_fd, lsrw_data, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
}
|
|
}
|
|
|
|
close (lsstat->r_fd);
|
|
// d_printf ("map_ls_statclose close file r_fd:%d", lsstat->r_fd);
|
|
if (lsstat->w_fd) {
|
|
close (lsstat->w_fd);
|
|
// d_printf ("map_ls_statclose close file w_fd:%d", lsstat->w_fd);
|
|
unlink (lsstat->fnametmp);
|
|
}
|
|
}
|
|
|
|
lsstat->fname[0] = '\0';
|
|
lsstat->fnametmp[0] = '\0';
|
|
lsstat->r_fd = 0;
|
|
lsstat->w_fd = 0;
|
|
};
|
|
|
|
|
|
/*********************************************************
|
|
* load the data, do not convert them yet.. but check
|
|
* if we need to load the data from r_fd or w_fd
|
|
*/
|
|
char *map_ls_loaddata (struct map_lsstat *lsstat, int *size, int ilon, int ilat) {
|
|
int flon = ilon - (ilon/MAP_LSHASHFACTOR)*MAP_LSHASHFACTOR;
|
|
int flat = ilat - (ilat/MAP_LSHASHFACTOR)*MAP_LSHASHFACTOR;
|
|
int nr = flon * MAP_LSHASHFACTOR + flat;
|
|
int fd;
|
|
uint64_t pos;
|
|
|
|
if (nr < 0 || nr >= MAP_LSHASHFACTOR*MAP_LSHASHFACTOR) {
|
|
d_printf ("WARN: map_ls_loaddata nr[%d] > MAP_LSHASHFACTOR^2[%d] ipos:%d,%d", nr, MAP_LSHASHFACTOR*MAP_LSHASHFACTOR, ilon, ilat);
|
|
return NULL;
|
|
}
|
|
|
|
if (lsstat->r_fd == 0) return NULL;
|
|
|
|
if (lsstat->w_fd > 0 && lsstat->w_lshpos[nr].pos != 0) {
|
|
/* w_fd has data? */
|
|
fd = lsstat->w_fd;
|
|
pos = lsstat->w_lshpos[nr].pos;
|
|
*size = lsstat->w_lshpos[nr].size;
|
|
}
|
|
else if (lsstat->r_lshpos[nr].pos != 0) {
|
|
/* r_fd has data ? */
|
|
fd = lsstat->r_fd;
|
|
pos = lsstat->r_lshpos[nr].pos;
|
|
*size = lsstat->r_lshpos[nr].size;
|
|
}
|
|
else {
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* read the data */
|
|
map_ls_hashdatacheck (*size);
|
|
if (lseek (fd, pos, SEEK_SET) < 0)
|
|
d_printf ("%s:%d error with lseek.", __FILE__, __LINE__);
|
|
if (read (fd, lshash_data, *size) != *size) {
|
|
d_printf ("ERROR: map_ls_loaddata: ERROR hashdata could not been loaded.");
|
|
d_printf (" lsstat fname:%s fnametmp:%s r_fd:%d, w_fd:%d", lsstat->fname, lsstat->fnametmp, lsstat->r_fd, lsstat->w_fd);
|
|
d_printf (" fd:%d pos:%lld size:%d", fd, pos, *size);
|
|
errorexit (1);
|
|
}
|
|
|
|
return lshash_data;
|
|
};
|
|
|
|
|
|
void map_ls_savedata (struct map_lsstat *lsstat, char *data, int size, int ilon, int ilat) {
|
|
int flon = ilon - (ilon/MAP_LSHASHFACTOR)*MAP_LSHASHFACTOR;
|
|
int flat = ilat - (ilat/MAP_LSHASHFACTOR)*MAP_LSHASHFACTOR;
|
|
int nr = flon * MAP_LSHASHFACTOR + flat;
|
|
int fd, i;
|
|
uint64_t pos;
|
|
struct map_lshmap olddatapos = {0, 0};
|
|
|
|
if (nr < 0 || nr >= MAP_LSHASHFACTOR*MAP_LSHASHFACTOR) {
|
|
d_printf ("WARN: map_ls_savedata nr[%d] > MAP_LSHASHFACTOR^2[%d] ipos:%d,%d", nr, MAP_LSHASHFACTOR*MAP_LSHASHFACTOR, ilon, ilat);
|
|
return;
|
|
}
|
|
|
|
if (lsstat->r_fd == 0) {
|
|
/* open new file and write empty data in it*/
|
|
map_ls_rwdatacheck (12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
memset (lsrw_data, 0x0, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
|
|
#if defined(__MINGW32CE__) || defined(_WIN32_WCE) || defined(__MINGW32__)
|
|
fd = open (lsstat->fname, O_CREAT|O_RDWR|O_TRUNC|_O_BINARY, 0644);
|
|
#else
|
|
fd = open (lsstat->fname, O_CREAT|O_RDWR|O_TRUNC, 0644);
|
|
#endif
|
|
if (fd == -1) {
|
|
/* Error... so free all unneeded memory */
|
|
d_printf ("ERROR: map_ls_savedata could not open file [%s]for writing.\n", lsstat->fname);
|
|
errorexit (-1);
|
|
}
|
|
// else d_printf ("map_ls_savedata open file %s fd:%d", lsstat->fname, fd);
|
|
write (fd, lsrw_data, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
}
|
|
else if (lsstat->w_fd > 0) {
|
|
/* new write file already opened?
|
|
* use new write file */
|
|
fd = lsstat->w_fd;
|
|
olddatapos = lsstat->w_lshpos[nr];
|
|
}
|
|
else if (lsstat->r_lshpos[nr].pos != 0) {
|
|
/* defrag of readfile still below 50% use read file else,
|
|
* open new write file */
|
|
fd = lsstat->r_fd;
|
|
pos = lseek (lsstat->r_fd, 0, SEEK_END);
|
|
if (pos < 0) d_printf ("%s:%d error with lseek.", __FILE__, __LINE__);
|
|
else if (lsstat->w_free[0].size > pos || lsstat->w_free[0].pos >= (MAP_LSFREECNT-2)) {
|
|
/*
|
|
* got over 25% lost already or maximum of free fields reached
|
|
*/
|
|
d_printf (" maximum of free blocks reached. cnt:%lld size:%d bytes, file:%s", lsstat->w_free[0].pos, lsstat->w_free[0].size, lsstat->fname);
|
|
close (lsstat->r_fd);
|
|
d_printf ("map_ls_savedata close file fd: %d", lsstat->r_fd);
|
|
snprintf (lsstat->fnametmp, LEN_FILENAME, "%s.tmp", lsstat->fname);
|
|
if (rename (lsstat->fname, lsstat->fnametmp) != 0) {
|
|
d_printf ("ERROR: map_ls_savedata rename(%s,%s) failed: %s", lsstat->fname, lsstat->fnametmp, strerror(errno));
|
|
errorexit (1);
|
|
}
|
|
|
|
/* open new file and write empty data in it*/
|
|
map_ls_rwdatacheck (12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
memset (lsrw_data, 0x0, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
lsstat->w_fd = open (lsstat->fname, O_CREAT|O_RDWR|O_TRUNC, 0644);
|
|
if (lsstat->w_fd <= 0) {
|
|
/* Error... so free all unneeded memory */
|
|
d_printf ("ERROR: map_ls_savedata could not open file [%s]for writing: ", lsstat->fname, strerror(errno));
|
|
errorexit (-1);
|
|
}
|
|
// else d_printf ("map_ls_savedata open file %s w_fd:%d", lsstat->fname, lsstat->w_fd);
|
|
write (lsstat->w_fd, lsrw_data, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
|
|
/* fill in new structure */
|
|
for (i = 0; i < MAP_LSHASHFACTOR*MAP_LSHASHFACTOR; i++) {
|
|
lsstat->w_lshpos[i].pos = 0;
|
|
lsstat->w_lshpos[i].size = 0;
|
|
if (i < MAP_LSFREECNT) {
|
|
lsstat->w_free[i].pos = 0;
|
|
lsstat->w_free[i].size = 0;
|
|
}
|
|
}
|
|
|
|
/* reopen old file for reading */
|
|
#if defined(__MINGW32CE__) || defined(_WIN32_WCE) || defined(__MINGW32__)
|
|
lsstat->r_fd = open (lsstat->fnametmp, O_RDONLY | _O_BINARY);
|
|
#else
|
|
lsstat->r_fd = open (lsstat->fnametmp, O_RDONLY);
|
|
#endif
|
|
if (lsstat->r_fd <= 0) {
|
|
/* Error... so free all unneeded memory */
|
|
d_printf ("ERROR: map_ls_savedata could not open file [%s] for reading: ", lsstat->fnametmp, strerror(errno));
|
|
errorexit (-1);
|
|
}
|
|
fd = lsstat->w_fd;
|
|
olddatapos = lsstat->w_lshpos[nr];
|
|
}
|
|
else {
|
|
olddatapos = lsstat->r_lshpos[nr];
|
|
}
|
|
}
|
|
else {
|
|
fd = lsstat->r_fd;
|
|
olddatapos = lsstat->r_lshpos[nr];
|
|
}
|
|
|
|
/*
|
|
* write datablock, and mark
|
|
*/
|
|
if ((pos = lseek (fd, 0, SEEK_END)) < 0)
|
|
d_printf ("%s:%d error with lseek.", __FILE__, __LINE__);
|
|
if ((i = write (fd, data, size)) < size) {
|
|
d_printf ("ERROR: map_ls_savedata written bytes are not as many as requested. i:%d size:%d error:%s", i, size, strerror (errno));
|
|
errorexit (1);
|
|
}
|
|
|
|
/*
|
|
* mark data as free
|
|
*/
|
|
if (olddatapos.pos > 0) {
|
|
lsstat->w_free[lsstat->w_free[0].pos+1] = olddatapos;
|
|
lsstat->w_free[0].pos++;
|
|
lsstat->w_free[0].size = lsstat->w_free[0].size +olddatapos.size;
|
|
}
|
|
|
|
/*
|
|
* setup fd and r_fd and w_fd
|
|
*/
|
|
if (lsstat->r_fd == 0)
|
|
lsstat->r_fd = fd;
|
|
if (fd == lsstat->r_fd) {
|
|
lsstat->w_fd = 0;
|
|
lsstat->r_lshpos[nr].pos = pos;
|
|
lsstat->r_lshpos[nr].size = size;
|
|
}
|
|
else {
|
|
lsstat->w_fd = fd;
|
|
lsstat->w_lshpos[nr].pos = pos;
|
|
lsstat->w_lshpos[nr].size = size;
|
|
}
|
|
lsstat->changed = 1;
|
|
|
|
/* if we have already alot unused data inside the
|
|
* w_fd close it, so we can later on create a new file */
|
|
if (lsstat->w_fd >0 && lsstat->w_free[0].pos >= MAP_LSFREECNT/2) map_ls_statclose (lsstat);
|
|
};
|
|
|
|
|
|
/************************************************************
|
|
* convert hash to datablock and return also it's size
|
|
*/
|
|
char *map_ls_hash2data (struct map_hash *mh, int *size) {
|
|
struct map_way *mw;
|
|
struct map_area *ma;
|
|
struct map_place *mp;
|
|
struct map_poi *mpoi;
|
|
struct map_lshentry lsh;
|
|
int obj_cnt, j, cur_size;
|
|
char *woutpos = NULL;
|
|
uint64_t ui64; /* datatypes needed for convert */
|
|
uint32_t ui32;
|
|
uint16_t ui16;
|
|
uint8_t ui8;
|
|
|
|
/*
|
|
* write ways
|
|
*/
|
|
*size = MAP_LSSIZE_HASH;
|
|
lsh.ways = 0;
|
|
lsh.areas = 0;
|
|
lsh.pois = 0;
|
|
lsh.places = 0;
|
|
lsh.ncnt = 0;
|
|
lsh.pcnt = 0;
|
|
lsh.ccnt = 0;
|
|
|
|
map_ls_hashdatacheck (*size);
|
|
woutpos = lshash_data+MAP_LSSIZE_HASH; /* the end of lshentry */
|
|
|
|
mw = mh->ways;
|
|
obj_cnt = 0;
|
|
while (mw && obj_cnt < mh->wayscnt) {
|
|
obj_cnt++;
|
|
if (mw != NULL) {
|
|
/* check if the allocated memory is enought */
|
|
cur_size = 2;
|
|
if (mw->name) cur_size += strlen (mw->name);
|
|
if (mw->ref) cur_size += strlen (mw->ref);
|
|
lsh.ccnt += cur_size;
|
|
*size = *size + MAP_LSSIZE_WAY + mw->p_cnt * MAP_LSSIZE_POS + mw->n_cnt * MAP_LSSIZE_WAYNODE + cur_size;
|
|
|
|
map_ls_hashdatacheckpos (*size, &woutpos);
|
|
|
|
/* save the basic data */
|
|
ui64 = mw->id; /* id */
|
|
ui64 = (ui64 << MAP_BITS_SUBID) | mw->subid;
|
|
woutpos = mempush (woutpos, &ui64, 8);
|
|
ui8 = mw->type; /* type */
|
|
woutpos = mempush (woutpos, &ui8, 1);
|
|
ui8 = mw->flags; /* flags */
|
|
woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
/* name */
|
|
ui8 = 0x0;
|
|
if (mw->name) woutpos = mempush (woutpos, mw->name, strlen (mw->name)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
/* ref */
|
|
if (mw->ref) woutpos = mempush (woutpos, mw->ref, strlen (mw->ref)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
ui16 = mw->n_cnt; /* n_cnt */
|
|
woutpos = mempush (woutpos, &ui16, 2);
|
|
|
|
ui16 = mw->p_cnt; /* p_cnt */
|
|
woutpos = mempush (woutpos, &ui16, 2);
|
|
|
|
/* save the waynodes */
|
|
for (j = 0; j < mw->n_cnt; j++) {
|
|
woutpos = mempush (woutpos, &mw->n[j].d.lon, 4);
|
|
woutpos = mempush (woutpos, &mw->n[j].d.lat, 4);
|
|
ui64 = mw->n[j].d_id;
|
|
woutpos = mempush (woutpos, &ui64, 8);
|
|
ui16 = mw->n[j].d_subid;
|
|
woutpos = mempush (woutpos, &ui16, 2);
|
|
ui16 = mw->n[j].d_pnr;
|
|
woutpos = mempush (woutpos, &ui16, 2);
|
|
ui16 = mw->n[j].pnr;
|
|
woutpos = mempush (woutpos, &ui16, 2);
|
|
ui8 = mw->n[j].flags;
|
|
woutpos = mempush (woutpos, &ui8, 1);
|
|
lsh.ncnt++;
|
|
}
|
|
|
|
/* save the points */
|
|
for (j = 0; j < mw->p_cnt; j++) {
|
|
woutpos = mempush (woutpos, &mw->p[j].lon, 4);
|
|
woutpos = mempush (woutpos, &mw->p[j].lat, 4);
|
|
lsh.pcnt++;
|
|
}
|
|
|
|
/* write the way on disk and increase ways counter */
|
|
lsh.ways++; // add the next way
|
|
}
|
|
|
|
mw = mw->next;
|
|
}
|
|
if (mw)
|
|
d_printf ("%s:%d map_save_hash all ways saved but mw != NULL (%p)", __FILE__, __LINE__, mw);
|
|
/*
|
|
* write the areas
|
|
*/
|
|
ma = mh->areas;
|
|
obj_cnt = 0;
|
|
while (ma && obj_cnt < mh->areascnt) {
|
|
obj_cnt++;
|
|
if (ma != NULL) {
|
|
/* check if the allocated memory is enought */
|
|
*size = *size + MAP_LSSIZE_AREA + ma->p_cnt * MAP_LSSIZE_POS;
|
|
map_ls_hashdatacheckpos (*size, &woutpos);
|
|
|
|
/* save the basic data */
|
|
ui64 = (ma->id << MAP_BITS_SUBID) | ma->subid; /* id */
|
|
woutpos = mempush (woutpos, &ui64, 8);
|
|
ui8 = ma->type; /* type */
|
|
woutpos = mempush (woutpos, &ui8, 1);
|
|
ui8 = ma->flags; /* flags */
|
|
woutpos = mempush (woutpos, &ui8, 1);
|
|
ui16 = ma->p_cnt; /* p_cnt */
|
|
woutpos = mempush (woutpos, &ui16, 2);
|
|
/* save the points */
|
|
for (j = 0; j < ma->p_cnt; j++) {
|
|
woutpos = mempush (woutpos, &ma->p[j].lon, 4);
|
|
woutpos = mempush (woutpos, &ma->p[j].lat, 4);
|
|
lsh.pcnt++;
|
|
}
|
|
/* write the way on disk and increase ways counter */
|
|
lsh.areas++; // add the next way
|
|
}
|
|
ma = ma->next;
|
|
}
|
|
if (ma)
|
|
d_printf ("%s:%d map_save_hash all areas saved but ma != NULL (%p)", __FILE__, __LINE__, ma);
|
|
|
|
/*
|
|
* save place data
|
|
*/
|
|
mp = mh->places;
|
|
obj_cnt = 0;
|
|
while (mp && obj_cnt < mh->placescnt) {
|
|
obj_cnt++;
|
|
if (mp != NULL) {
|
|
/* check if the allocated memory is enought */
|
|
cur_size = 5;
|
|
if (mp->country) cur_size += strlen (mp->country);
|
|
if (mp->state) cur_size += strlen (mp->state);
|
|
if (mp->district) cur_size += strlen (mp->district);
|
|
if (mp->name) cur_size += strlen (mp->name);
|
|
if (mp->postalcode) cur_size += strlen (mp->postalcode);
|
|
lsh.ccnt += cur_size;
|
|
*size = *size + cur_size + MAP_LSSIZE_PLACE;
|
|
map_ls_hashdatacheckpos (*size, &woutpos);
|
|
|
|
/* save the basic data */
|
|
woutpos = mempush (woutpos, &mp->lon, 4);
|
|
woutpos = mempush (woutpos, &mp->lat, 4);
|
|
|
|
ui64 = mp->id; /* id */
|
|
woutpos = mempush (woutpos, &ui64, 8);
|
|
ui8 = mp->type; /* type */
|
|
woutpos = mempush (woutpos, &ui8, 1);
|
|
ui32 = mp->population; /* population */
|
|
woutpos = mempush (woutpos, &ui32, 4);
|
|
|
|
/* save the text */
|
|
ui8 = 0x0;
|
|
/* country */
|
|
if (mp->country) woutpos = mempush (woutpos, mp->country, strlen (mp->country)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
/* state */
|
|
if (mp->state) woutpos = mempush (woutpos, mp->state, strlen (mp->state)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
/* district */
|
|
if (mp->district) woutpos = mempush (woutpos, mp->district, strlen (mp->district)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
/* name */
|
|
if (mp->name) woutpos = mempush (woutpos, mp->name, strlen (mp->name)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
/* postalcode */
|
|
if (mp->postalcode) woutpos = mempush (woutpos, mp->postalcode, strlen (mp->postalcode)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
lsh.places++; // add the next way
|
|
}
|
|
|
|
mp = mp->next;
|
|
}
|
|
if (mp)
|
|
d_printf ("%s:%d map_save_hash all places saved but mp != NULL (%p)", __FILE__, __LINE__, mp);
|
|
|
|
/*
|
|
* save poi data
|
|
*/
|
|
mpoi = mh->pois;
|
|
obj_cnt = 0;
|
|
while (mpoi && obj_cnt < mh->poiscnt) {
|
|
obj_cnt++;
|
|
if (mpoi != NULL) {
|
|
/* check if the allocated memory is enought */
|
|
cur_size = 2;
|
|
if (mpoi->name) cur_size += strlen (mpoi->name);
|
|
if (mpoi->additional) cur_size += strlen (mpoi->additional);
|
|
lsh.ccnt += cur_size;
|
|
*size = *size + cur_size + MAP_LSSIZE_POI;
|
|
map_ls_hashdatacheckpos (*size, &woutpos);
|
|
|
|
/* save the basic data */
|
|
woutpos = mempush (woutpos, &mpoi->lon, 4);
|
|
woutpos = mempush (woutpos, &mpoi->lat, 4);
|
|
ui64 = mpoi->id; /* id */
|
|
woutpos = mempush (woutpos, &ui64, 8);
|
|
ui8 = mpoi->type; /* type */
|
|
woutpos = mempush (woutpos, &ui8, 1);
|
|
/* save the text */
|
|
ui8 = 0x0;
|
|
|
|
/* name */
|
|
if (mpoi->name) woutpos = mempush (woutpos, mpoi->name, strlen (mpoi->name)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
/* additional */
|
|
if (mpoi->additional) woutpos = mempush (woutpos, mpoi->additional, strlen (mpoi->additional)+1);
|
|
else woutpos = mempush (woutpos, &ui8, 1);
|
|
|
|
lsh.pois++; // add the next poi
|
|
}
|
|
|
|
mpoi = mpoi->next;
|
|
}
|
|
if (mpoi)
|
|
d_printf ("%s:%d map_save_hash all pois saved but mpoi != NULL (%p)", __FILE__, __LINE__, mpoi);
|
|
|
|
/* setup the lsh into the file */
|
|
woutpos = lshash_data;
|
|
ui32 = lsh.ways;
|
|
woutpos = mempush (woutpos, &ui32, 4);
|
|
ui32 = lsh.areas;
|
|
woutpos = mempush (woutpos, &ui32, 4);
|
|
ui32 = lsh.pois;
|
|
woutpos = mempush (woutpos, &ui32, 4);
|
|
ui32 = lsh.places;
|
|
woutpos = mempush (woutpos, &ui32, 4);
|
|
ui32 = lsh.ncnt;
|
|
woutpos = mempush (woutpos, &ui32, 4);
|
|
ui32 = lsh.pcnt;
|
|
woutpos = mempush (woutpos, &ui32, 4);
|
|
ui32 = lsh.ccnt;
|
|
woutpos = mempush (woutpos, &ui32, 4);
|
|
|
|
return lshash_data;
|
|
};
|
|
|
|
|
|
/*******************************************************************
|
|
* convert data into hash
|
|
*/
|
|
struct map_hash *map_ls_data2hash (char *data, int size) {
|
|
struct map_lshentry lsh;
|
|
struct map_hash *mh = NULL;
|
|
struct map_way *way = NULL;
|
|
struct map_area *area = NULL;
|
|
struct map_place *place = NULL;
|
|
struct map_poi *poi = NULL;
|
|
char *inpos;
|
|
int i, cnt;
|
|
uint64_t ui64; /* datatypes needed for convert */
|
|
uint32_t ui32;
|
|
uint16_t ui16;
|
|
uint8_t ui8;
|
|
|
|
inpos = data;
|
|
inpos = mempop (inpos, &ui32, 4);
|
|
lsh.ways = ui32;
|
|
inpos = mempop (inpos, &ui32, 4);
|
|
lsh.areas = ui32;
|
|
inpos = mempop (inpos, &ui32, 4);
|
|
lsh.pois = ui32;
|
|
inpos = mempop (inpos, &ui32, 4);
|
|
lsh.places = ui32;
|
|
inpos = mempop (inpos, &ui32, 4);
|
|
lsh.ncnt = ui32;
|
|
inpos = mempop (inpos, &ui32, 4);
|
|
lsh.pcnt = ui32;
|
|
inpos = mempop (inpos, &ui32, 4);
|
|
lsh.ccnt = ui32;
|
|
|
|
mh = map_hash_alloc (map_hash_calc_size (lsh.ways, lsh.areas, lsh.pois, lsh.places, lsh.pcnt, lsh.ncnt, lsh.ccnt));
|
|
mh->wayscnt = lsh.ways;
|
|
mh->areascnt = lsh.areas;
|
|
mh->poiscnt = lsh.pois;
|
|
mh->placescnt = lsh.places;
|
|
|
|
if (lsh.ways > 0) {
|
|
/*
|
|
* prepare and read the way
|
|
*/
|
|
way = (struct map_way*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
mh->ways = way;
|
|
mh->wayscnt = lsh.ways;
|
|
|
|
/* read all ways */
|
|
for (cnt = 0; cnt < lsh.ways; cnt++) {
|
|
/* load basic data */
|
|
inpos = mempop (inpos, &ui64, 8);
|
|
way->subid = ui64 % (1<<MAP_BITS_SUBID);
|
|
way->id = (ui64 >> MAP_BITS_SUBID);
|
|
inpos = mempop (inpos, &ui8, 1);
|
|
way->type = ui8;
|
|
inpos = mempop (inpos, &ui8, 1);
|
|
way->flags = ui8;
|
|
inpos = memstrpop (inpos, way->name, &i);
|
|
if (i >= MAP_W_NAMELEN) {
|
|
static int _only_once_ = 1;
|
|
if (_only_once_) d_printf ("%s:%d ERROR in %s: i(%d) > MAP_W_NAMELEN(%d). Name:'%s'", __FILE__, __LINE__, __FUNCTION__, i, MAP_W_NAMELEN, way->name);
|
|
_only_once_ = 0;
|
|
i = MAP_W_NAMELEN - 1;
|
|
}
|
|
way->name[i] = 0;
|
|
inpos = memstrpop (inpos, way->ref, &i);
|
|
if (i >= MAP_W_NAMELEN) {
|
|
static int _only_once_ = 1;
|
|
if (_only_once_) d_printf ("%s:%d ERROR in %s: i(%d) > MAP_W_NAMELEN(%d). Ref:'%s'", __FILE__, __LINE__, __FUNCTION__, i, MAP_W_NAMELEN, way->ref);
|
|
_only_once_ = 0;
|
|
i = MAP_W_NAMELEN - 1;
|
|
}
|
|
way->ref[i] = 0;
|
|
|
|
inpos = mempop (inpos, &ui16, 2);
|
|
way->n_cnt = ui16;
|
|
inpos = mempop (inpos, &ui16, 2);
|
|
way->p_cnt = ui16;
|
|
|
|
/* save the waynodes */
|
|
way->n = (struct map_waynode*)way->data;
|
|
for (i = 0; i < way->n_cnt; i++) {
|
|
inpos = mempop (inpos, &way->n[i].d.lon, 4);
|
|
inpos = mempop (inpos, &way->n[i].d.lat, 4);
|
|
inpos = mempop (inpos, &ui64, 8);
|
|
way->n[i].d_id = ui64;
|
|
inpos = mempop (inpos, &ui16, 2);
|
|
way->n[i].d_subid = ui16;
|
|
inpos = mempop (inpos, &ui16, 2);
|
|
way->n[i].d_pnr = ui16;
|
|
inpos = mempop (inpos, &ui16, 2);
|
|
way->n[i].pnr = ui16;
|
|
inpos = mempop (inpos, &ui8, 1);
|
|
way->n[i].flags = ui8;
|
|
}
|
|
|
|
/* save the points */
|
|
way->p = (struct map_pos*) (way->data + (way->n_cnt * sizeof (struct map_waynode)));
|
|
for (i = 0; i < way->p_cnt; i++) {
|
|
inpos = mempop (inpos, &way->p[i].lon, 4);
|
|
inpos = mempop (inpos, &way->p[i].lat, 4);
|
|
}
|
|
|
|
mh->free = mh->free + map_way_getsize (way);
|
|
if (cnt < (lsh.ways-1)) way->next = (struct map_way*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
else way->next = NULL;
|
|
way = (struct map_way*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* prepare to read the areas
|
|
*/
|
|
if (lsh.areas > 0) {
|
|
area = (struct map_area*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
mh->areascnt = lsh.areas;
|
|
mh->areas = area;
|
|
area->prev = NULL;
|
|
|
|
/* read all area */
|
|
for (cnt = 0; cnt < lsh.areas; cnt++) {
|
|
/* load and setup basic data */
|
|
area->next = NULL;
|
|
|
|
inpos = mempop (inpos, &ui64, 8);
|
|
area->subid = ui64 % (1<<MAP_BITS_SUBID);
|
|
area->id = ui64;
|
|
inpos = mempop (inpos, &ui8, 1);
|
|
area->type = ui8;
|
|
inpos = mempop (inpos, &ui8, 1);
|
|
area->flags = ui8;
|
|
inpos = mempop (inpos, &ui16, 2);
|
|
area->p_cnt = ui16;
|
|
|
|
/* read the points */
|
|
area->p = (struct map_pos*) area->data;
|
|
for (i = 0; i < area->p_cnt; i++) {
|
|
inpos = mempop (inpos, &area->p[i].lon, 4);
|
|
inpos = mempop (inpos, &area->p[i].lat, 4);
|
|
}
|
|
|
|
mh->free = mh->free + map_area_getsize (area);
|
|
|
|
/*
|
|
* check if we are still in order
|
|
*/
|
|
while (area->prev != NULL && area->type < area->prev->type) {
|
|
struct map_area *parea = area->prev;
|
|
|
|
/* nighbours pointers change */
|
|
if (parea->prev == NULL) mh->areas = area;
|
|
else parea->prev->next = area;
|
|
if (area->next != NULL) area->next->prev = parea;
|
|
|
|
/* swap area->prev with area */
|
|
parea->next = area->next;
|
|
area->prev = parea->prev;
|
|
parea->prev = area;
|
|
area->next = parea;
|
|
|
|
/* check next */
|
|
area = parea;
|
|
}
|
|
for (;area->next != NULL; area = area->next);
|
|
|
|
if (cnt < (lsh.areas-1)) {
|
|
area->next = (struct map_area*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
area->next->prev = area;
|
|
area = area->next;
|
|
}
|
|
else area->next = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* prepare to read places
|
|
*/
|
|
if (lsh.places > 0) {
|
|
place = (struct map_place*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
mh->placescnt = lsh.places;
|
|
mh->places = place;
|
|
|
|
/* read all area */
|
|
for (cnt = 0; (cnt < lsh.places); cnt++) {
|
|
/* load basic data */
|
|
inpos = mempop (inpos, &place->lon, 4);
|
|
inpos = mempop (inpos, &place->lat, 4);
|
|
inpos = mempop (inpos, &ui64, 8);
|
|
place->id = ui64;
|
|
inpos = mempop (inpos, &ui8, 1);
|
|
place->type = ui8;
|
|
inpos = mempop (inpos, &ui32, 4);
|
|
place->population = ui32;
|
|
|
|
/* read the text data */
|
|
place->country = place->data;
|
|
inpos = memstrpop (inpos, place->country, &i);
|
|
|
|
place->state = place->country+i;
|
|
inpos = memstrpop (inpos, place->state, &i);
|
|
|
|
place->district = place->state+i;
|
|
inpos = memstrpop (inpos, place->district, &i);
|
|
|
|
place->name = place->district+i;
|
|
inpos = memstrpop (inpos, place->name, &i);
|
|
|
|
place->postalcode = place->name+i;
|
|
inpos = memstrpop (inpos, place->postalcode, &i);
|
|
|
|
mh->free = mh->free + map_place_getsize (place);
|
|
if (cnt < (lsh.places-1)) place->next = (struct map_place*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
else place->next = NULL;
|
|
place = (struct map_place*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* prepare to read pois
|
|
*/
|
|
if (lsh.pois > 0) {
|
|
poi = (struct map_poi*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
mh->poiscnt = lsh.pois;
|
|
mh->pois = poi;
|
|
|
|
/* read all area */
|
|
for (cnt = 0; (cnt < lsh.pois); cnt++) {
|
|
/* load basic data */
|
|
inpos = mempop (inpos, &poi->lon, 4);
|
|
inpos = mempop (inpos, &poi->lat, 4);
|
|
inpos = mempop (inpos, &ui64, 8);
|
|
poi->id = ui64;
|
|
inpos = mempop (inpos, &ui8, 1);
|
|
poi->type = ui8;
|
|
|
|
/* read the text data */
|
|
poi->name = poi->data;
|
|
inpos = memstrpop (inpos, poi->name, &i);
|
|
|
|
poi->additional = poi->name+i;
|
|
inpos = memstrpop (inpos, poi->additional, &i);
|
|
|
|
mh->free = mh->free + map_poi_getsize (poi);
|
|
if (cnt < (lsh.pois-1)) poi->next = (struct map_poi*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
else poi->next = NULL;
|
|
poi = (struct map_poi*) map_hash_getfree_aligned (mh, POINTERALIGNMENT);
|
|
}
|
|
}
|
|
|
|
mh->pos.ilon = 0;
|
|
mh->pos.ilat = 0;
|
|
if ((char*)mh->free - (char*)mh > mh->datasize) {
|
|
d_printf ("ERROR: map_ls_data2hash buffer overrun! memsize:%d < mh->free-mh:%d", mh->datasize, (char*)mh->free - (char*)mh);
|
|
errorexit(1);
|
|
}
|
|
DELFLAG(mh->status, MS_changed);
|
|
|
|
return mh;
|
|
};
|
|
|
|
|
|
/****************************************************************
|
|
* load hash data
|
|
*/
|
|
struct map_hash *map_load_hash (int ilon, int ilat) {
|
|
char fn[LEN_FILENAME];
|
|
struct map_lsstat *mlss = NULL;
|
|
char *data;
|
|
int size;
|
|
struct map_hash *mh;
|
|
|
|
map_ls_get_filename (fn, LEN_FILENAME, ilon, ilat);
|
|
mlss = map_ls_statget (fn);
|
|
if (mlss == NULL) {
|
|
d_printf ("WARN: map_load_hash no pointer to mlss structure (fn:%s igeo:%d,%d)", fn, ilon, ilat);
|
|
return NULL;
|
|
}
|
|
data = map_ls_loaddata (mlss, &size, ilon, ilat);
|
|
if (data == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
mh = map_ls_data2hash (data, size);
|
|
if (mh) {
|
|
mh->pos.ilon = ilon;
|
|
mh->pos.ilat = ilat;
|
|
}
|
|
|
|
return mh;
|
|
};
|
|
|
|
|
|
int map_save_hash (struct map_hash *mh) {
|
|
char fn[LEN_FILENAME];
|
|
struct map_lsstat *mlss = NULL;
|
|
char *data;
|
|
int size = 0;
|
|
|
|
if (ISNOTFLAG(mh->status, MS_changed)) return 0;
|
|
|
|
map_ls_get_filename (fn, LEN_FILENAME, mh->pos.ilon, mh->pos.ilat);
|
|
mlss = map_ls_statget (fn);
|
|
if (mlss == NULL) {
|
|
d_printf ("WARN: map_save_hash no pointer to mlss structure (fn:%s igeo:%d,%d)", fn, mh->pos.ilon, mh->pos.ilat);
|
|
return 0;
|
|
}
|
|
|
|
data = map_ls_hash2data (mh, &size);
|
|
map_ls_savedata (mlss, data, size, mh->pos.ilon, mh->pos.ilat);
|
|
DELFLAG(mh->status, MS_changed);
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
void map_save_all () {
|
|
int i = 0;
|
|
|
|
while (i < mhash_max) for (i = 0; i < mhash_max; i++) {
|
|
if (mhash[i]) if (ISFLAG(mhash[i]->status, MS_changed)) {
|
|
if (mhash[i] != map_hash_geti (mhash[i]->pos.ilon , mhash[i]->pos.ilat, MHLOAD_NONE))
|
|
d_printf ("%s:%d something went wrong mhash != map_hash_get",__FILE__,__LINE__);
|
|
if (map_save_hash (mhash[i]) == 0) DELFLAG(mhash[i]->status, MS_changed);
|
|
break;
|
|
}
|
|
main_wnd_update ();
|
|
}
|
|
|
|
for (i = 0; i < MAP_LSSTAT_MAX; i++) {
|
|
if (mlsstat[i].fname[0] != '\0')
|
|
map_ls_statclose (&mlsstat[i]);
|
|
}
|
|
};
|
|
|
|
|
|
/****************************************************************************
|
|
* defrag the map data files, needed to decrease the size of the file.
|
|
*/
|
|
void map_defrag () {
|
|
DIR *directory = NULL;
|
|
struct dirent *direntry = NULL;
|
|
static struct stat filestat;
|
|
char fn[LEN_FILENAME];
|
|
|
|
d_printf ("map_defrag");
|
|
directory = opendir(cfg.mappath);
|
|
if (directory == NULL) {
|
|
d_printf ("map_defrag opendir (%s) failed:%s", cfg.mappath, strerror (errno));
|
|
return;
|
|
}
|
|
|
|
while ((direntry = readdir (directory)) != NULL) {
|
|
snprintf (fn, LEN_FILENAME, "%s/%s", cfg.mappath, direntry->d_name);
|
|
if (strncmp ((direntry->d_name+strlen(direntry->d_name)-8), ".mapdata", 9) == 0 && stat(fn, &filestat) == 0)
|
|
if (S_ISREG(filestat.st_mode)) {
|
|
d_printf ("defrag file:%s size:%ld", direntry->d_name, filestat.st_size);
|
|
map_defragfile (fn);
|
|
stat(fn, &filestat);
|
|
d_printf (" now:%s size:%ld", direntry->d_name, filestat.st_size);
|
|
}
|
|
}
|
|
|
|
closedir (directory);
|
|
};
|
|
|
|
|
|
void map_defragfile (char *fn) {
|
|
struct map_lsstat *lsstat = NULL;
|
|
int i;
|
|
|
|
/* get lsstat from old file */
|
|
map_clear();
|
|
lsstat = map_ls_statopen (fn);
|
|
d_printf ("lsstat r_fd:%d, w_fd:%d", lsstat->r_fd, lsstat->w_fd);
|
|
|
|
/* reopen file and create write file */
|
|
close (lsstat->r_fd);
|
|
d_printf ("map_defragfile close file r_fd:%d", lsstat->r_fd);
|
|
snprintf (lsstat->fnametmp, LEN_FILENAME, "%s.tmp", lsstat->fname);
|
|
if (rename (lsstat->fname, lsstat->fnametmp) != 0) {
|
|
d_printf ("ERROR: map_defragfile rename(%s,%s) failed: %s", lsstat->fname, lsstat->fnametmp, strerror(errno));
|
|
errorexit (1);
|
|
}
|
|
|
|
/* open new file and write empty data in it*/
|
|
map_ls_rwdatacheck (12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
memset (lsrw_data, 0x0, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
lsstat->w_fd = open (lsstat->fname, O_CREAT|O_RDWR|O_TRUNC, 0644);
|
|
if (lsstat->w_fd <= 0) {
|
|
/* Error... so quit */
|
|
d_printf ("ERROR: map_defrag could not open file [%s]for writing: ", lsstat->fname, strerror(errno));
|
|
errorexit (-1);
|
|
}
|
|
write (lsstat->w_fd, lsrw_data, 12*(MAP_LSHASHFACTOR*MAP_LSHASHFACTOR+MAP_LSFREECNT));
|
|
|
|
/* fill in new structure */
|
|
for (i = 0; i < MAP_LSHASHFACTOR*MAP_LSHASHFACTOR; i++) {
|
|
lsstat->w_lshpos[i].pos = 0;
|
|
lsstat->w_lshpos[i].size = 0;
|
|
if (i < MAP_LSFREECNT) {
|
|
lsstat->w_free[i].pos = 0;
|
|
lsstat->w_free[i].size = 0;
|
|
}
|
|
}
|
|
|
|
/* reopen old file for reading */
|
|
#if defined(__MINGW32CE__) || defined(_WIN32_WCE) || defined(__MINGW32__)
|
|
lsstat->r_fd = open (lsstat->fnametmp, O_RDONLY | _O_BINARY);
|
|
#else
|
|
lsstat->r_fd = open (lsstat->fnametmp, O_RDONLY);
|
|
#endif
|
|
if (lsstat->r_fd <= 0) {
|
|
/* Error... so free all unneeded memory */
|
|
d_printf ("ERROR: map_defrag could not open file [%s] for reading: ", lsstat->fnametmp, strerror(errno));
|
|
errorexit (-1);
|
|
}
|
|
else {
|
|
d_printf ("map_defragfile open file %s r_fd:%d", lsstat->fnametmp, lsstat->r_fd);
|
|
}
|
|
|
|
lsstat->changed = 1;
|
|
map_ls_statclose (lsstat);
|
|
map_init ();
|
|
};
|
|
|