myrg_open.c 5.27 KB
Newer Older
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3 4 5 6
   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.
7

bk@work.mysql.com's avatar
bk@work.mysql.com committed
8 9 10 11
   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.
12

bk@work.mysql.com's avatar
bk@work.mysql.com committed
13 14 15 16
   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 */

17
/* open a MyISAM MERGE table */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
18

19
#include "myrg_def.h"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
20 21 22 23 24 25
#include <stddef.h>
#include <errno.h>
#ifdef VMS
#include "mrg_static.c"
#endif

serg@serg.mysql.com's avatar
serg@serg.mysql.com committed
26
/*
27
	open a MyISAM MERGE table
serg@serg.mysql.com's avatar
serg@serg.mysql.com committed
28 29
	if handle_locking is 0 then exit with error if some table is locked
	if handle_locking is 1 then wait if table is locked
bk@work.mysql.com's avatar
bk@work.mysql.com committed
30 31 32
*/


33
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
34
{
35 36
  int save_errno,errpos=0;
  uint files=0,i,dir_length,length,key_parts;
37
  ulonglong file_offset=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
38
  char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
39
  MYRG_INFO *m_info=0;
40 41
  File fd;
  IO_CACHE file;
42
  MI_INFO *isam=0;
43
  uint found_merge_insert_method= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
44 45
  DBUG_ENTER("myrg_open");

46 47
  LINT_INIT(key_parts);

48 49
  bzero((char*) &file,sizeof(file));
  if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,4),
50
		  O_RDONLY | O_SHARE,MYF(0))) < 0)
51 52 53
     goto err;
   errpos=1;
   if (init_io_cache(&file, fd, 4*IO_SIZE, READ_CACHE, 0, 0,
54
		    MYF(MY_WME | MY_NABP)))
55 56
     goto err;
   errpos=2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
57
  dir_length=dirname_part(name_buff,name);
58
  while ((length=my_b_gets(&file,buff,FN_REFLEN-1)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
59
  {
60
    if ((end=buff+length)[-1] == '\n')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
61
      end[-1]='\0';
62
    if (buff[0] && buff[0] != '#')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
63 64
      files++;
  }
65 66

  my_b_seek(&file, 0);
67
  while ((length=my_b_gets(&file,buff,FN_REFLEN-1)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
68
  {
69
    if ((end=buff+length)[-1] == '\n')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
70
      end[-1]='\0';
71 72 73
    if (!buff[0])
      continue;		/* Skip empty lines */
    if (buff[0] == '#')
bk@work.mysql.com's avatar
bk@work.mysql.com committed
74
    {
75
      if (!strncmp(buff+1,"INSERT_METHOD=",14))
76 77
      {			/* Lookup insert method */
	int tmp=find_type(buff+15,&merge_insert_method,2);
78
	found_merge_insert_method = (uint) (tmp >= 0 ? tmp : 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
79
      }
80 81
      continue;		/* Skip comments */
    }
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
82

83 84 85 86 87 88
    if (!test_if_hard_path(buff))
    {
      VOID(strmake(name_buff+dir_length,buff,
                   sizeof(name_buff)-1-dir_length));
      VOID(cleanup_dirname(buff,name_buff));
    }
serg@serg.mysql.com's avatar
serg@serg.mysql.com committed
89
    if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0))))
90 91
      goto err;
    if (!m_info)                                /* First file */
92 93 94 95 96 97 98 99 100 101 102
    {
      key_parts=isam->s->base.key_parts;
      if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) +
                                           files*sizeof(MYRG_TABLE) +
                                           key_parts*sizeof(long),
                                           MYF(MY_WME|MY_ZEROFILL))))
        goto err;
      if (files)
      {
        m_info->open_tables=(MYRG_TABLE *) (m_info+1);
        m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files);
103 104
        m_info->tables= files;
        files= 0;
105 106 107 108
      }
      m_info->reclength=isam->s->base.reclength;
      errpos=3;
    }
109 110 111
    m_info->open_tables[files].table= isam;
    m_info->open_tables[files].file_offset=(my_off_t) file_offset;
    file_offset+=isam->state->data_file_length;
112
    files++;
serg@serg.mylan's avatar
serg@serg.mylan committed
113
    if (m_info->reclength != isam->s->base.reclength)
114
    {
115
      my_errno=HA_ERR_WRONG_MRG_TABLE_DEF;
116
      goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
117
    }
118 119 120 121
    m_info->options|= isam->s->options;
    m_info->records+= isam->state->records;
    m_info->del+= isam->state->del;
    m_info->data_file_length+= isam->state->data_file_length;
122
    for (i=0; i < key_parts; i++)
123 124
      m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] /
                                     m_info->tables);
serg@serg.mysql.com's avatar
serg@serg.mysql.com committed
125
  }
126

serg@serg.mylan's avatar
serg@serg.mylan committed
127
  if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO),
128
                                                  MYF(MY_WME | MY_ZEROFILL))))
serg@serg.mylan's avatar
serg@serg.mylan committed
129
    goto err;
130 131
  /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */
  m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA);
132
  m_info->merge_insert_method= found_merge_insert_method;
133

bk@work.mysql.com's avatar
bk@work.mysql.com committed
134 135 136 137 138
  if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L)
  {
    my_errno=HA_ERR_RECORD_FILE_FULL;
    goto err;
  }
serg@serg.mylan's avatar
serg@serg.mylan committed
139
  m_info->keys= files ? isam->s->base.keys : 0;
140
  bzero((char*) &m_info->by_key,sizeof(m_info->by_key));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
141

142
  /* this works ok if the table list is empty */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
143 144 145
  m_info->end_table=m_info->open_tables+files;
  m_info->last_used_table=m_info->open_tables;

146 147
  VOID(my_close(fd,MYF(0)));
  end_io_cache(&file);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
148 149 150 151 152 153 154 155 156
  m_info->open_list.data=(void*) m_info;
  pthread_mutex_lock(&THR_LOCK_open);
  myrg_open_list=list_add(myrg_open_list,&m_info->open_list);
  pthread_mutex_unlock(&THR_LOCK_open);
  DBUG_RETURN(m_info);

err:
  save_errno=my_errno;
  switch (errpos) {
157 158 159
  case 3:
    while (files)
      mi_close(m_info->open_tables[--files].table);
160 161
    my_free((char*) m_info,MYF(0));
    /* Fall through */
162 163 164
  case 2:
    end_io_cache(&file);
    /* Fall through */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
165
  case 1:
166
    VOID(my_close(fd,MYF(0)));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
167 168 169 170
  }
  my_errno=save_errno;
  DBUG_RETURN (NULL);
}