~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
16
/*
17
  locking of isam-tables.
18
  reads info from a isam-table. Must be first request before doing any furter
19
  calls to any isamfunktion.  Is used to allow many process use the same
20
  isamdatabase.
21
*/
22
1130.3.28 by Monty Taylor
Moved heapdef.h and myisamdef.h to *_priv.h for easier filtering for include guard check.
23
#include "myisam_priv.h"
2281.5.1 by Muhammad Umair
Merged charset declarations of global_charset_info.h and charset_info.h into charset.h header file.
24
#include <drizzled/charset.h>
492.1.7 by Monty Taylor
Moved test() to its own file.
25
#include <drizzled/util/test.h>
1 by brian
clean slate
26
916.1.35 by Padraig O'Sullivan
Removing the last of LIST from the MyISAM storage engine.
27
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
28
using namespace drizzled;
916.1.35 by Padraig O'Sullivan
Removing the last of LIST from the MyISAM storage engine.
29
1 by brian
clean slate
30
	/* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
31
32
int mi_lock_database(MI_INFO *info, int lock_type)
33
{
34
  int error;
482 by Brian Aker
Remove uint.
35
  uint32_t count;
1 by brian
clean slate
36
  MYISAM_SHARE *share=info->s;
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
37
#if defined(FULL_LOG) || defined(_lint)
482 by Brian Aker
Remove uint.
38
  uint32_t flag;
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
39
#endif
916.1.37 by Padraig O'Sullivan
Added a lock to protect an instance of the in_use list. Thanks Monty for
40
916.1.35 by Padraig O'Sullivan
Removing the last of LIST from the MyISAM storage engine.
41
  if (!info->s->in_use)
42
    info->s->in_use= new list<Session *>;
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
43
1 by brian
clean slate
44
  if (lock_type == F_EXTRA_LCK)                 /* Used by TMP tables */
45
  {
46
    ++share->w_locks;
47
    ++share->tot_locks;
48
    info->lock_type= lock_type;
916.1.35 by Padraig O'Sullivan
Removing the last of LIST from the MyISAM storage engine.
49
    info->s->in_use->push_front(info->in_use);
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
50
    return(0);
1 by brian
clean slate
51
  }
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
52
#if defined(FULL_LOG) || defined(_lint)
53
  flag=0;
54
#endif
1 by brian
clean slate
55
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
56
  error=0;
1 by brian
clean slate
57
  if (share->kfile >= 0)		/* May only be false on windows */
58
  {
59
    switch (lock_type) {
60
    case F_UNLCK:
61
      if (info->lock_type == F_RDLCK)
62
	count= --share->r_locks;
63
      else
64
	count= --share->w_locks;
65
      --share->tot_locks;
66
      if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
67
      {
1909.1.1 by Brian Aker
Encapsulation of IO_CACHE.
68
	if (info->rec_cache.end_io_cache())
1 by brian
clean slate
69
	{
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
70
	  error=errno;
1 by brian
clean slate
71
          mi_print_error(info->s, HA_ERR_CRASHED);
72
	  mi_mark_crashed(info);
73
	}
74
      }
75
      if (!count)
76
      {
77
	if (share->changed && !share->w_locks)
78
	{
79
    if ((info->s->mmaped_length != info->s->state.state.data_file_length) &&
80
        (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
81
    {
82
      mi_remap_file(info, info->s->state.state.data_file_length);
83
      info->s->nonmmaped_inserts= 0;
84
    }
85
	  share->state.process= share->last_process=share->this_process;
86
	  share->state.unique=   info->last_unique=  info->this_unique;
87
	  share->state.update_count= info->last_loop= ++info->this_loop;
88
          if (mi_state_info_write(share->kfile, &share->state, 1))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
89
	    error=errno;
1 by brian
clean slate
90
	  share->changed=0;
1115.1.2 by Brian Aker
Taylor the defaults for MyISAM for its "tmp" behavior.
91
          share->not_flushed=1;
1 by brian
clean slate
92
	  if (error)
93
          {
94
            mi_print_error(info->s, HA_ERR_CRASHED);
95
	    mi_mark_crashed(info);
96
          }
97
	}
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
98
#if defined(FULL_LOG) || defined(_lint)
1 by brian
clean slate
99
	if (info->lock_type != F_EXTRA_LCK)
100
	{
101
	  if (share->r_locks)
102
	  {					/* Only read locks left */
103
	    flag=1;
104
	  }
105
	  else if (!share->w_locks)
106
	  {					/* No more locks */
107
	    flag=1;
108
	  }
109
	}
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
110
#endif
1 by brian
clean slate
111
      }
112
      info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
113
      info->lock_type= F_UNLCK;
916.1.35 by Padraig O'Sullivan
Removing the last of LIST from the MyISAM storage engine.
114
      info->s->in_use->remove(info->in_use);
1 by brian
clean slate
115
      break;
116
    case F_RDLCK:
117
      if (info->lock_type == F_WRLCK)
118
      {
119
        /*
120
          Change RW to READONLY
121
122
          mysqld does not turn write locks to read locks,
123
          so we're never here in mysqld.
124
        */
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
125
#if defined(FULL_LOG) || defined(_lint)
1 by brian
clean slate
126
	if (share->w_locks == 1)
127
	{
128
	  flag=1;
129
	}
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
130
#endif
1 by brian
clean slate
131
	share->w_locks--;
132
	share->r_locks++;
133
	info->lock_type=lock_type;
134
	break;
135
      }
136
      if (!share->r_locks && !share->w_locks)
137
      {
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
138
#if defined(FULL_LOG) || defined(_lint)
1 by brian
clean slate
139
	flag=1;
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
140
#endif
1 by brian
clean slate
141
	if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
142
	{
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
143
	  error=errno;
1 by brian
clean slate
144
	  break;
145
	}
146
	if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
147
	{
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
148
	  error=errno;
149
	  errno=error;
1 by brian
clean slate
150
	  break;
151
	}
152
      }
398.1.10 by Monty Taylor
Actually removed VOID() this time.
153
      _mi_test_if_changed(info);
1 by brian
clean slate
154
      share->r_locks++;
155
      share->tot_locks++;
156
      info->lock_type=lock_type;
916.1.35 by Padraig O'Sullivan
Removing the last of LIST from the MyISAM storage engine.
157
      info->s->in_use->push_front(info->in_use);
1 by brian
clean slate
158
      break;
159
    case F_WRLCK:
160
      if (info->lock_type == F_RDLCK)
161
      {						/* Change READONLY to RW */
162
	if (share->r_locks == 1)
163
	{
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
164
#if defined(FULL_LOG) || defined(_lint)
1 by brian
clean slate
165
	  flag=1;
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
166
#endif
1 by brian
clean slate
167
	  share->r_locks--;
168
	  share->w_locks++;
169
	  info->lock_type=lock_type;
170
	  break;
171
	}
172
      }
173
      if (!(share->options & HA_OPTION_READ_ONLY_DATA))
174
      {
175
	if (!share->w_locks)
176
	{
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
177
#if defined(FULL_LOG) || defined(_lint)
1 by brian
clean slate
178
	  flag=1;
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
179
#endif
1 by brian
clean slate
180
	  if (!share->r_locks)
181
	  {
182
	    if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
183
	    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
184
	      error=errno;
185
	      errno=error;
1 by brian
clean slate
186
	      break;
187
	    }
188
	  }
189
	}
190
      }
398.1.10 by Monty Taylor
Actually removed VOID() this time.
191
      _mi_test_if_changed(info);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
192
1 by brian
clean slate
193
      info->lock_type=lock_type;
194
      share->w_locks++;
195
      share->tot_locks++;
916.1.35 by Padraig O'Sullivan
Removing the last of LIST from the MyISAM storage engine.
196
      info->s->in_use->push_front(info->in_use);
1 by brian
clean slate
197
      break;
198
    default:
199
      break;				/* Impossible */
200
    }
201
  }
202
#ifdef __WIN__
203
  else
204
  {
205
    /*
206
       Check for bad file descriptors if this table is part
207
       of a merge union. Failing to capture this may cause
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
208
       a crash on windows if the table is renamed and
1 by brian
clean slate
209
       later on referenced by the merge table.
210
     */
211
    if( info->owned_by_merge && (info->s)->kfile < 0 )
212
    {
213
      error = HA_ERR_NO_SUCH_TABLE;
214
    }
215
  }
216
#endif
217
#if defined(FULL_LOG) || defined(_lint)
218
  lock_type|=(int) (flag << 8);		/* Set bit to set if real lock */
481 by Brian Aker
Remove all of uchar.
219
  myisam_log_command(MI_LOG_LOCK,info,(unsigned char*) &lock_type,sizeof(lock_type),
1 by brian
clean slate
220
		     error);
221
#endif
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
222
  return(error);
1 by brian
clean slate
223
} /* mi_lock_database */
224
225
226
/****************************************************************************
227
 ** functions to read / write the state
228
****************************************************************************/
229
230
int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
231
{
232
  if (info->lock_type == F_UNLCK)
233
  {
234
    MYISAM_SHARE *share=info->s;
235
    if (!share->tot_locks)
236
    {
237
      if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
238
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
239
	int error=errno ? errno : -1;
240
	errno=error;
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
241
	return(1);
1 by brian
clean slate
242
      }
243
    }
244
    if (check_keybuffer)
398.1.10 by Monty Taylor
Actually removed VOID() this time.
245
      _mi_test_if_changed(info);
1 by brian
clean slate
246
  }
247
  else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
248
  {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
249
    errno=EACCES;				/* Not allowed to change */
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
250
    return(-1);				/* when have read_lock() */
1 by brian
clean slate
251
  }
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
252
  return(0);
1 by brian
clean slate
253
} /* _mi_readinfo */
254
255
256
/*
257
  Every isam-function that uppdates the isam-database MUST end with this
258
  request
259
*/
260
482 by Brian Aker
Remove uint.
261
int _mi_writeinfo(register MI_INFO *info, uint32_t operation)
1 by brian
clean slate
262
{
263
  int error,olderror;
264
  MYISAM_SHARE *share=info->s;
265
266
  error=0;
267
  if (share->tot_locks == 0)
268
  {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
269
    olderror=errno;			/* Remember last error */
1 by brian
clean slate
270
    if (operation)
271
    {					/* Two threads can't be here */
272
      share->state.process= share->last_process=   share->this_process;
273
      share->state.unique=  info->last_unique=	   info->this_unique;
274
      share->state.update_count= info->last_loop= ++info->this_loop;
275
      if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
276
	olderror=errno;
1 by brian
clean slate
277
    }
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
278
    errno=olderror;
1 by brian
clean slate
279
  }
280
  else if (operation)
281
    share->changed= 1;			/* Mark keyfile changed */
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
282
  return(error);
1 by brian
clean slate
283
} /* _mi_writeinfo */
284
285
286
	/* Test if someone has changed the database */
287
	/* (Should be called after readinfo) */
288
289
int _mi_test_if_changed(register MI_INFO *info)
290
{
291
  MYISAM_SHARE *share=info->s;
292
  if (share->state.process != share->last_process ||
293
      share->state.unique  != info->last_unique ||
294
      share->state.update_count != info->last_loop)
295
  {						/* Keyfile has changed */
296
    share->last_process=share->state.process;
297
    info->last_unique=	share->state.unique;
298
    info->last_loop=	share->state.update_count;
299
    info->update|=	HA_STATE_WRITTEN;	/* Must use file on next */
300
    info->data_changed= 1;			/* For mi_is_changed */
301
    return 1;
302
  }
303
  return (!(info->update & HA_STATE_AKTIV) ||
304
	  (info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED |
305
			   HA_STATE_KEY_CHANGED)));
306
} /* _mi_test_if_changed */
307
308
309
/*
310
  Put a mark in the .MYI file that someone is updating the table
311
312
313
  DOCUMENTATION
314
315
  state.open_count in the .MYI file is used the following way:
316
  - For the first change of the .MYI file in this process open_count is
317
    incremented by mi_mark_file_change(). (We have a write lock on the file
318
    when this happens)
319
  - In mi_close() it's decremented by _mi_decrement_open_count() if it
320
    was incremented in the same process.
321
322
  This mean that if we are the only process using the file, the open_count
77.1.96 by Monty Taylor
Removed skip-external-locking.
323
  tells us if the MYISAM file wasn't properly closed.*/
1 by brian
clean slate
324
325
326
int _mi_mark_file_changed(MI_INFO *info)
327
{
481 by Brian Aker
Remove all of uchar.
328
  unsigned char buff[3];
1 by brian
clean slate
329
  register MYISAM_SHARE *share=info->s;
330
331
  if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
332
  {
333
    share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED |
334
			   STATE_NOT_OPTIMIZED_KEYS);
335
    if (!share->global_changed)
336
    {
337
      share->global_changed=1;
338
      share->state.open_count++;
339
    }
340
    if (!share->temporary)
341
    {
342
      mi_int2store(buff,share->state.open_count);
343
      buff[2]=1;				/* Mark that it's changed */
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
344
      return(my_pwrite(share->kfile,buff,sizeof(buff),
1 by brian
clean slate
345
                            sizeof(share->state.header),
346
                            MYF(MY_NABP)));
347
    }
348
  }
51.1.87 by Jay Pipes
Removed/replaced DBUG symbols
349
  return(0);
1 by brian
clean slate
350
}
351
352
353
/*
354
  This is only called by close or by extra(HA_FLUSH) if the OS has the pwrite()
355
  call.  In these context the following code should be safe!
356
 */
357
358
int _mi_decrement_open_count(MI_INFO *info)
359
{
481 by Brian Aker
Remove all of uchar.
360
  unsigned char buff[2];
1 by brian
clean slate
361
  register MYISAM_SHARE *share=info->s;
362
  int lock_error=0,write_error=0;
363
  if (share->global_changed)
364
  {
482 by Brian Aker
Remove uint.
365
    uint32_t old_lock=info->lock_type;
1 by brian
clean slate
366
    share->global_changed=0;
367
    lock_error=mi_lock_database(info,F_WRLCK);
368
    /* Its not fatal even if we couldn't get the lock ! */
369
    if (share->state.open_count > 0)
370
    {
371
      share->state.open_count--;
372
      mi_int2store(buff,share->state.open_count);
373
      write_error=my_pwrite(share->kfile,buff,sizeof(buff),
374
			    sizeof(share->state.header),
375
			    MYF(MY_NABP));
376
    }
377
    if (!lock_error)
378
      lock_error=mi_lock_database(info,old_lock);
379
  }
380
  return test(lock_error || write_error);
381
}