⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ha_tina.cc

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2003 MySQL 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 *//*  Make sure to look at ha_tina.h for more details.  First off, this is a play thing for me, there are a number of things wrong with it: *) It was designed for csv and therefor its performance is highly questionable. *) Indexes have not been implemented. This is because the files can be traded in and out of the table directory without having to worry about rebuilding anything. *) NULLs and "" are treated equally (like a spreadsheet). *) There was in the beginning no point to anyone seeing this other then me, so there is a good chance that I haven't quite documented it well. *) Less design, more "make it work" Now there are a few cool things with it: *) Errors can result in corrupted data files. *) Data files can be read by spreadsheets directly.TODO: *) Move to a block system for larger files *) Error recovery, its all there, just need to finish it *) Document how the chains work. -Brian*/#ifdef USE_PRAGMA_IMPLEMENTATION#pragma implementation        // gcc: Class implementation#endif#include "mysql_priv.h"#ifdef HAVE_CSV_DB#include "ha_tina.h"#include <sys/mman.h>/* Stuff for shares */pthread_mutex_t tina_mutex;static HASH tina_open_tables;static int tina_init= 0;handlerton tina_hton= {  "CSV",  SHOW_OPTION_YES,  "CSV storage engine",   DB_TYPE_CSV_DB,  NULL,    /* One needs to be written! */  0,       /* slot */  0,       /* savepoint size. */  NULL,    /* close_connection */  NULL,    /* savepoint */  NULL,    /* rollback to savepoint */  NULL,    /* release savepoint */  NULL,    /* commit */  NULL,    /* rollback */  NULL,    /* prepare */  NULL,    /* recover */  NULL,    /* commit_by_xid */  NULL,    /* rollback_by_xid */  NULL,    /* create_cursor_read_view */  NULL,    /* set_cursor_read_view */  NULL,    /* close_cursor_read_view */  HTON_CAN_RECREATE};/***************************************************************************** ** TINA tables *****************************************************************************//*  Used for sorting chains with qsort().*/int sort_set (tina_set *a, tina_set *b){  /*    We assume that intervals do not intersect. So, it is enought to compare    any two points. Here we take start of intervals for comparison.  */  return ( a->begin > b->begin ? -1 : ( a->begin < b->begin ? 1 : 0 ) );}static byte* tina_get_key(TINA_SHARE *share,uint *length,                          my_bool not_used __attribute__((unused))){  *length=share->table_name_length;  return (byte*) share->table_name;}/*  Reloads the mmap file.*/int get_mmap(TINA_SHARE *share, int write){  DBUG_ENTER("ha_tina::get_mmap");  if (share->mapped_file && munmap(share->mapped_file, share->file_stat.st_size))    DBUG_RETURN(1);  if (my_fstat(share->data_file, &share->file_stat, MYF(MY_WME)) == -1)    DBUG_RETURN(1);  if (share->file_stat.st_size)   {    if (write)      share->mapped_file= (byte *)mmap(NULL, share->file_stat.st_size,                                        PROT_READ|PROT_WRITE, MAP_SHARED,                                       share->data_file, 0);    else      share->mapped_file= (byte *)mmap(NULL, share->file_stat.st_size,                                        PROT_READ, MAP_PRIVATE,                                       share->data_file, 0);    if ((share->mapped_file ==(caddr_t)-1))     {      /*        Bad idea you think? See the problem is that nothing actually checks        the return value of ::rnd_init(), so tossing an error is about        it for us.        Never going to happen right? :)      */      my_message(errno, "Woops, blew up opening a mapped file", 0);      DBUG_ASSERT(0);      DBUG_RETURN(1);    }  }  else     share->mapped_file= NULL;  DBUG_RETURN(0);}/*  Simple lock controls.*/static TINA_SHARE *get_share(const char *table_name, TABLE *table){  TINA_SHARE *share;  char *tmp_name;  uint length;  if (!tina_init)  {    /* Hijack a mutex for init'ing the storage engine */    pthread_mutex_lock(&LOCK_mysql_create_db);    if (!tina_init)    {      tina_init++;      VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));      (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,                       (hash_get_key) tina_get_key,0,0);    }    pthread_mutex_unlock(&LOCK_mysql_create_db);  }  pthread_mutex_lock(&tina_mutex);  length=(uint) strlen(table_name);  if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,                                        (byte*) table_name,                                        length)))  {    char data_file_name[FN_REFLEN];    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),                         &share, sizeof(*share),                         &tmp_name, length+1,                         NullS))     {      pthread_mutex_unlock(&tina_mutex);      return NULL;    }    share->use_count=0;    share->table_name_length=length;    share->table_name=tmp_name;    strmov(share->table_name,table_name);    fn_format(data_file_name, table_name, "", ".CSV",MY_REPLACE_EXT|MY_UNPACK_FILENAME);    if (my_hash_insert(&tina_open_tables, (byte*) share))      goto error;    thr_lock_init(&share->lock);    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);    if ((share->data_file= my_open(data_file_name, O_RDWR|O_APPEND,                                   MYF(0))) == -1)      goto error2;    /* We only use share->data_file for writing, so we scan to the end to append */    if (my_seek(share->data_file, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)      goto error2;    share->mapped_file= NULL; // We don't know the state since we just allocated it    if (get_mmap(share, 0) > 0)      goto error3;  }  share->use_count++;  pthread_mutex_unlock(&tina_mutex);  return share;error3:  my_close(share->data_file,MYF(0));error2:  thr_lock_delete(&share->lock);  pthread_mutex_destroy(&share->mutex);error:  pthread_mutex_unlock(&tina_mutex);  my_free((gptr) share, MYF(0));  return NULL;}/*   Free lock controls.*/static int free_share(TINA_SHARE *share){  DBUG_ENTER("ha_tina::free_share");  pthread_mutex_lock(&tina_mutex);  int result_code= 0;  if (!--share->use_count){    /* Drop the mapped file */    if (share->mapped_file)       munmap(share->mapped_file, share->file_stat.st_size);    result_code= my_close(share->data_file,MYF(0));    hash_delete(&tina_open_tables, (byte*) share);    thr_lock_delete(&share->lock);    pthread_mutex_destroy(&share->mutex);    my_free((gptr) share, MYF(0));  }  pthread_mutex_unlock(&tina_mutex);  DBUG_RETURN(result_code);}bool tina_end(){  if (tina_init)  {    hash_free(&tina_open_tables);    VOID(pthread_mutex_destroy(&tina_mutex));  }  tina_init= 0;  return FALSE;}/*   Finds the end of a line.  Currently only supports files written on a UNIX OS.*/byte * find_eoln(byte *data, off_t begin, off_t end) {  for (off_t x= begin; x < end; x++)     if (data[x] == '\n')      return data + x;  return 0;}ha_tina::ha_tina(TABLE *table_arg)  :handler(&tina_hton, table_arg),  /*    These definitions are found in hanler.h    These are not probably completely right.  */  current_position(0), next_position(0), chain_alloced(0),  chain_size(DEFAULT_CHAIN_LENGTH), records_is_known(0){  /* Set our original buffers from pre-allocated memory */  buffer.set(byte_buffer, IO_SIZE, system_charset_info);  chain= chain_buffer;}/*  Encode a buffer into the quoted format.*/int ha_tina::encode_quote(byte *buf) {  char attribute_buffer[1024];  String attribute(attribute_buffer, sizeof(attribute_buffer), &my_charset_bin);  buffer.length(0);  for (Field **field=table->field ; *field ; field++)  {    const char *ptr;    const char *end_ptr;    (*field)->val_str(&attribute,&attribute);    ptr= attribute.ptr();    end_ptr= attribute.length() + ptr;    buffer.append('"');    while (ptr < end_ptr)     {      if (*ptr == '"')      {        buffer.append('\\');        buffer.append('"');        *ptr++;      }      else if (*ptr == '\r')      {        buffer.append('\\');        buffer.append('r');        *ptr++;      }      else if (*ptr == '\\')      {        buffer.append('\\');        buffer.append('\\');        *ptr++;      }      else if (*ptr == '\n')      {        buffer.append('\\');        buffer.append('n');        *ptr++;      }      else        buffer.append(*ptr++);    }    buffer.append('"');    buffer.append(',');  }  // Remove the comma, add a line feed  buffer.length(buffer.length() - 1);  buffer.append('\n');  //buffer.replace(buffer.length(), 0, "\n", 1);  return (buffer.length());}/*  chain_append() adds delete positions to the chain that we use to keep track of space.*/int ha_tina::chain_append(){  if ( chain_ptr != chain && (chain_ptr -1)->end == current_position)    (chain_ptr -1)->end= next_position;  else   {    /* We set up for the next position */    if ((off_t)(chain_ptr - chain) == (chain_size -1))    {      off_t location= chain_ptr - chain;      chain_size += DEFAULT_CHAIN_LENGTH;      if (chain_alloced)      {        /* Must cast since my_malloc unlike malloc doesn't have a void ptr */        if ((chain= (tina_set *)my_realloc((gptr)chain,chain_size,MYF(MY_WME))) == NULL)          return -1;      }      else      {        tina_set *ptr= (tina_set *)my_malloc(chain_size * sizeof(tina_set),MYF(MY_WME));        memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));        chain= ptr;        chain_alloced++;      }      chain_ptr= chain + location;    }    chain_ptr->begin= current_position;    chain_ptr->end= next_position;    chain_ptr++;  }  return 0;}/*   Scans for a row.*/int ha_tina::find_current_row(byte *buf){  byte *mapped_ptr= (byte *)share->mapped_file + current_position;  byte *end_ptr;  DBUG_ENTER("ha_tina::find_current_row");  /* EOF should be counted as new line */  if ((end_ptr=  find_eoln(share->mapped_file, current_position, share->file_stat.st_size)) == 0)    DBUG_RETURN(HA_ERR_END_OF_FILE);  for (Field **field=table->field ; *field ; field++)  {    buffer.length(0);    mapped_ptr++; // Increment past the first quote    for(;mapped_ptr != end_ptr; mapped_ptr++)    {      //Need to convert line feeds!      if (*mapped_ptr == '"' &&           (((mapped_ptr[1] == ',') && (mapped_ptr[2] == '"')) || (mapped_ptr == end_ptr -1 )))      {        mapped_ptr += 2; // Move past the , and the "        break;      }       if (*mapped_ptr == '\\' && mapped_ptr != (end_ptr - 1))       {        mapped_ptr++;        if (*mapped_ptr == 'r')          buffer.append('\r');        else if (*mapped_ptr == 'n' )          buffer.append('\n');        else if ((*mapped_ptr == '\\') || (*mapped_ptr == '"'))          buffer.append(*mapped_ptr);        else  /* This could only happed with an externally created file */        {          buffer.append('\\');          buffer.append(*mapped_ptr);        }      }       else        buffer.append(*mapped_ptr);    }    (*field)->store(buffer.ptr(), buffer.length(), system_charset_info);  }  next_position= (end_ptr - share->mapped_file)+1;  /* Maybe use \N for null? */  memset(buf, 0, table->s->null_bytes); /* We do not implement nulls! */  DBUG_RETURN(0);}/*  If frm_error() is called in table.cc this is called to find out what file  extensions exist for this handler.*/static const char *ha_tina_exts[] = {  ".CSV",  NullS};const char **ha_tina::bas_ext() const{  return ha_tina_exts;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -