diff options
Diffstat (limited to 'sql/sql_map.cc')
-rw-r--r-- | sql/sql_map.cc | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/sql/sql_map.cc b/sql/sql_map.cc new file mode 100644 index 00000000000..4578b85d10a --- /dev/null +++ b/sql/sql_map.cc @@ -0,0 +1,147 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + 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 __GNUC__ +#pragma implementation // gcc: Class implementation +#endif + +#include "mysql_priv.h" +#ifdef HAVE_MMAP +#include <sys/mman.h> +#include <sys/stat.h> +#endif + +#ifndef MAP_NORESERVE +#define MAP_NORESERVE 0 // For IRIX +#endif + +mapped_files::mapped_files(const my_string filename,byte *magic,uint magic_length) +{ +#ifdef HAVE_MMAP + name=my_strdup(filename,MYF(0)); + use_count=1; + error=0; + map=0; + size=0; + if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) >= 0) + { + struct stat stat_buf; + if (!fstat(file,&stat_buf)) + { + if (!(map=(byte*) mmap(0,(size=(ulong) stat_buf.st_size),PROT_READ, + MAP_SHARED | MAP_NORESERVE,file, + 0L))) + { + error=errno; + my_printf_error(0,"Can't map file: %s, errno: %d",MYF(0), + (my_string) name,error); + } + } + if (map && memcmp(map,magic,magic_length)) + { + my_printf_error(0,"Wrong magic in %s",MYF(0),name); + VOID(munmap(map,size)); + map=0; + } + if (!map) + { + VOID(my_close(file,MYF(0))); + file= -1; + } + } +#endif +} + + +mapped_files::~mapped_files() +{ +#ifdef HAVE_MMAP + if (file >= 0) + { + VOID(munmap((caddr_t) map,size)); + VOID(my_close(file,MYF(0))); + file= -1; map=0; + } + my_free(name,MYF(0)); +#endif +} + + +static I_List<mapped_files> maps_in_use; + +/* +** Check if a file is mapped. If it is, then return pointer to old map, +** else alloc new object +*/ + +mapped_files *map_file(const my_string name,byte *magic,uint magic_length) +{ +#ifdef HAVE_MMAP + VOID(pthread_mutex_lock(&LOCK_mapped_file)); + I_List_iterator<mapped_files> list(maps_in_use); + mapped_files *map; + char path[FN_REFLEN]; + sprintf(path,"%s/%s/%s.uniq",mysql_data_home,current_thd->db,name); + (void) unpack_filename(path,path); + + while ((map=list++)) + { + if (!strcmp(path,map->name)) + break; + } + if (!map) + { + map=new mapped_files(path,magic,magic_length); + maps_in_use.append(map); + } + else + { + map->use_count++; + if (!map->map) + my_printf_error(0,"Can't map file: %s, error: %d",MYF(0),path, + map->error); + } + VOID(pthread_mutex_unlock(&LOCK_mapped_file)); + return map; +#else + return NULL; +#endif +} + +/* +** free the map if there are no more users for it +*/ + +void unmap_file(mapped_files *map) +{ +#ifdef HAVE_MMAP + VOID(pthread_mutex_lock(&LOCK_mapped_file)); + if (!map->use_count--) + delete map; + VOID(pthread_mutex_unlock(&LOCK_mapped_file)); +#endif +} + +/***************************************************************************** +** Instansiate templates +*****************************************************************************/ + +#ifdef __GNUC__ +/* Used templates */ +template class I_List<mapped_files>; +template class I_List_iterator<mapped_files>; +#endif |