~stewart/drizzle/embedded-innodb-create-select-transaction-arrgh

« back to all changes in this revision

Viewing changes to storage/myisam/mi_locking.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
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
 
 
23
#include "ftdefs.h"
 
24
 
 
25
        /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
 
26
 
 
27
int mi_lock_database(MI_INFO *info, int lock_type)
 
28
{
 
29
  int error;
 
30
  uint count;
 
31
  MYISAM_SHARE *share=info->s;
 
32
  uint flag;
 
33
  DBUG_ENTER("mi_lock_database");
 
34
  DBUG_PRINT("enter",("lock_type: %d  old lock %d  r_locks: %u  w_locks: %u "
 
35
                      "global_changed:  %d  open_count: %u  name: '%s'",
 
36
                      lock_type, info->lock_type, share->r_locks,
 
37
                      share->w_locks,
 
38
                      share->global_changed, share->state.open_count,
 
39
                      share->index_file_name));
 
40
  if (share->options & HA_OPTION_READ_ONLY_DATA ||
 
41
      info->lock_type == lock_type)
 
42
    DBUG_RETURN(0);
 
43
  if (lock_type == F_EXTRA_LCK)                 /* Used by TMP tables */
 
44
  {
 
45
    ++share->w_locks;
 
46
    ++share->tot_locks;
 
47
    info->lock_type= lock_type;
 
48
    info->s->in_use= list_add(info->s->in_use, &info->in_use);
 
49
    DBUG_RETURN(0);
 
50
  }
 
51
 
 
52
  flag=error=0;
 
53
  pthread_mutex_lock(&share->intern_lock);
 
54
  if (share->kfile >= 0)                /* May only be false on windows */
 
55
  {
 
56
    switch (lock_type) {
 
57
    case F_UNLCK:
 
58
      ftparser_call_deinitializer(info);
 
59
      if (info->lock_type == F_RDLCK)
 
60
        count= --share->r_locks;
 
61
      else
 
62
        count= --share->w_locks;
 
63
      --share->tot_locks;
 
64
      if (info->lock_type == F_WRLCK && !share->w_locks &&
 
65
          !share->delay_key_write && flush_key_blocks(share->key_cache,
 
66
                                                      share->kfile,FLUSH_KEEP))
 
67
      {
 
68
        error=my_errno;
 
69
        mi_print_error(info->s, HA_ERR_CRASHED);
 
70
        mi_mark_crashed(info);          /* Mark that table must be checked */
 
71
      }
 
72
      if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
 
73
      {
 
74
        if (end_io_cache(&info->rec_cache))
 
75
        {
 
76
          error=my_errno;
 
77
          mi_print_error(info->s, HA_ERR_CRASHED);
 
78
          mi_mark_crashed(info);
 
79
        }
 
80
      }
 
81
      if (!count)
 
82
      {
 
83
        DBUG_PRINT("info",("changed: %u  w_locks: %u",
 
84
                           (uint) share->changed, share->w_locks));
 
85
        if (share->changed && !share->w_locks)
 
86
        {
 
87
#ifdef HAVE_MMAP
 
88
    if ((info->s->mmaped_length != info->s->state.state.data_file_length) &&
 
89
        (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
 
90
    {
 
91
      if (info->s->concurrent_insert)
 
92
        rw_wrlock(&info->s->mmap_lock);
 
93
      mi_remap_file(info, info->s->state.state.data_file_length);
 
94
      info->s->nonmmaped_inserts= 0;
 
95
      if (info->s->concurrent_insert)
 
96
        rw_unlock(&info->s->mmap_lock);
 
97
    }
 
98
#endif
 
99
          share->state.process= share->last_process=share->this_process;
 
100
          share->state.unique=   info->last_unique=  info->this_unique;
 
101
          share->state.update_count= info->last_loop= ++info->this_loop;
 
102
          if (mi_state_info_write(share->kfile, &share->state, 1))
 
103
            error=my_errno;
 
104
          share->changed=0;
 
105
          if (myisam_flush)
 
106
          {
 
107
            if (my_sync(share->kfile, MYF(0)))
 
108
              error= my_errno;
 
109
            if (my_sync(info->dfile, MYF(0)))
 
110
              error= my_errno;
 
111
          }
 
112
          else
 
113
            share->not_flushed=1;
 
114
          if (error)
 
115
          {
 
116
            mi_print_error(info->s, HA_ERR_CRASHED);
 
117
            mi_mark_crashed(info);
 
118
          }
 
119
        }
 
120
        if (info->lock_type != F_EXTRA_LCK)
 
121
        {
 
122
          if (share->r_locks)
 
123
          {                                     /* Only read locks left */
 
124
            flag=1;
 
125
            if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
 
126
                        MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
 
127
              error=my_errno;
 
128
          }
 
129
          else if (!share->w_locks)
 
130
          {                                     /* No more locks */
 
131
            flag=1;
 
132
            if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
 
133
                        MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
 
134
              error=my_errno;
 
135
          }
 
136
        }
 
137
      }
 
138
      info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
 
139
      info->lock_type= F_UNLCK;
 
140
      info->s->in_use= list_delete(info->s->in_use, &info->in_use);
 
141
      break;
 
142
    case F_RDLCK:
 
143
      if (info->lock_type == F_WRLCK)
 
144
      {
 
145
        /*
 
146
          Change RW to READONLY
 
147
 
 
148
          mysqld does not turn write locks to read locks,
 
149
          so we're never here in mysqld.
 
150
        */
 
151
        if (share->w_locks == 1)
 
152
        {
 
153
          flag=1;
 
154
          if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
155
                      MYF(MY_SEEK_NOT_DONE)))
 
156
          {
 
157
            error=my_errno;
 
158
            break;
 
159
          }
 
160
        }
 
161
        share->w_locks--;
 
162
        share->r_locks++;
 
163
        info->lock_type=lock_type;
 
164
        break;
 
165
      }
 
166
      if (!share->r_locks && !share->w_locks)
 
167
      {
 
168
        flag=1;
 
169
        if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
170
                    info->lock_wait | MY_SEEK_NOT_DONE))
 
171
        {
 
172
          error=my_errno;
 
173
          break;
 
174
        }
 
175
        if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
 
176
        {
 
177
          error=my_errno;
 
178
          VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
 
179
          my_errno=error;
 
180
          break;
 
181
        }
 
182
      }
 
183
      VOID(_mi_test_if_changed(info));
 
184
      share->r_locks++;
 
185
      share->tot_locks++;
 
186
      info->lock_type=lock_type;
 
187
      info->s->in_use= list_add(info->s->in_use, &info->in_use);
 
188
      break;
 
189
    case F_WRLCK:
 
190
      if (info->lock_type == F_RDLCK)
 
191
      {                                         /* Change READONLY to RW */
 
192
        if (share->r_locks == 1)
 
193
        {
 
194
          flag=1;
 
195
          if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
196
                      MYF(info->lock_wait | MY_SEEK_NOT_DONE)))
 
197
          {
 
198
            error=my_errno;
 
199
            break;
 
200
          }
 
201
          share->r_locks--;
 
202
          share->w_locks++;
 
203
          info->lock_type=lock_type;
 
204
          break;
 
205
        }
 
206
      }
 
207
      if (!(share->options & HA_OPTION_READ_ONLY_DATA))
 
208
      {
 
209
        if (!share->w_locks)
 
210
        {
 
211
          flag=1;
 
212
          if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
213
                      info->lock_wait | MY_SEEK_NOT_DONE))
 
214
          {
 
215
            error=my_errno;
 
216
            break;
 
217
          }
 
218
          if (!share->r_locks)
 
219
          {
 
220
            if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
 
221
            {
 
222
              error=my_errno;
 
223
              VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
 
224
                           info->lock_wait | MY_SEEK_NOT_DONE));
 
225
              my_errno=error;
 
226
              break;
 
227
            }
 
228
          }
 
229
        }
 
230
      }
 
231
      VOID(_mi_test_if_changed(info));
 
232
        
 
233
      info->lock_type=lock_type;
 
234
      info->invalidator=info->s->invalidator;
 
235
      share->w_locks++;
 
236
      share->tot_locks++;
 
237
      info->s->in_use= list_add(info->s->in_use, &info->in_use);
 
238
      break;
 
239
    default:
 
240
      break;                            /* Impossible */
 
241
    }
 
242
  }
 
243
#ifdef __WIN__
 
244
  else
 
245
  {
 
246
    /*
 
247
       Check for bad file descriptors if this table is part
 
248
       of a merge union. Failing to capture this may cause
 
249
       a crash on windows if the table is renamed and 
 
250
       later on referenced by the merge table.
 
251
     */
 
252
    if( info->owned_by_merge && (info->s)->kfile < 0 )
 
253
    {
 
254
      error = HA_ERR_NO_SUCH_TABLE;
 
255
    }
 
256
  }
 
257
#endif
 
258
  pthread_mutex_unlock(&share->intern_lock);
 
259
#if defined(FULL_LOG) || defined(_lint)
 
260
  lock_type|=(int) (flag << 8);         /* Set bit to set if real lock */
 
261
  myisam_log_command(MI_LOG_LOCK,info,(uchar*) &lock_type,sizeof(lock_type),
 
262
                     error);
 
263
#endif
 
264
  DBUG_RETURN(error);
 
265
} /* mi_lock_database */
 
266
 
 
267
 
 
268
/****************************************************************************
 
269
  The following functions are called by thr_lock() in threaded applications
 
270
****************************************************************************/
 
271
 
 
272
/*
 
273
  Create a copy of the current status for the table
 
274
 
 
275
  SYNOPSIS
 
276
    mi_get_status()
 
277
    param               Pointer to Myisam handler
 
278
    concurrent_insert   Set to 1 if we are going to do concurrent inserts
 
279
                        (THR_WRITE_CONCURRENT_INSERT was used)
 
280
*/
 
281
 
 
282
void mi_get_status(void* param, int concurrent_insert)
 
283
{
 
284
  MI_INFO *info=(MI_INFO*) param;
 
285
  DBUG_ENTER("mi_get_status");
 
286
  DBUG_PRINT("info",("key_file: %ld  data_file: %ld  concurrent_insert: %d",
 
287
                     (long) info->s->state.state.key_file_length,
 
288
                     (long) info->s->state.state.data_file_length,
 
289
                     concurrent_insert));
 
290
#ifndef DBUG_OFF
 
291
  if (info->state->key_file_length > info->s->state.state.key_file_length ||
 
292
      info->state->data_file_length > info->s->state.state.data_file_length)
 
293
    DBUG_PRINT("warning",("old info:  key_file: %ld  data_file: %ld",
 
294
                          (long) info->state->key_file_length,
 
295
                          (long) info->state->data_file_length));
 
296
#endif
 
297
  info->save_state=info->s->state.state;
 
298
  info->state= &info->save_state;
 
299
  info->append_insert_at_end= concurrent_insert;
 
300
  DBUG_VOID_RETURN;
 
301
}
 
302
 
 
303
 
 
304
void mi_update_status(void* param)
 
305
{
 
306
  MI_INFO *info=(MI_INFO*) param;
 
307
  /*
 
308
    Because someone may have closed the table we point at, we only
 
309
    update the state if its our own state.  This isn't a problem as
 
310
    we are always pointing at our own lock or at a read lock.
 
311
    (This is enforced by thr_multi_lock.c)
 
312
  */
 
313
  if (info->state == &info->save_state)
 
314
  {
 
315
#ifndef DBUG_OFF
 
316
    DBUG_PRINT("info",("updating status:  key_file: %ld  data_file: %ld",
 
317
                       (long) info->state->key_file_length,
 
318
                       (long) info->state->data_file_length));
 
319
    if (info->state->key_file_length < info->s->state.state.key_file_length ||
 
320
        info->state->data_file_length < info->s->state.state.data_file_length)
 
321
      DBUG_PRINT("warning",("old info:  key_file: %ld  data_file: %ld",
 
322
                            (long) info->s->state.state.key_file_length,
 
323
                            (long) info->s->state.state.data_file_length));
 
324
#endif
 
325
    info->s->state.state= *info->state;
 
326
    info->state= &info->s->state.state;
 
327
  }
 
328
  info->append_insert_at_end= 0;
 
329
 
 
330
  /*
 
331
    We have to flush the write cache here as other threads may start
 
332
    reading the table before mi_lock_database() is called
 
333
  */
 
334
  if (info->opt_flag & WRITE_CACHE_USED)
 
335
  {
 
336
    if (end_io_cache(&info->rec_cache))
 
337
    {
 
338
      mi_print_error(info->s, HA_ERR_CRASHED);
 
339
      mi_mark_crashed(info);
 
340
    }
 
341
    info->opt_flag&= ~WRITE_CACHE_USED;
 
342
  }
 
343
}
 
344
 
 
345
 
 
346
void mi_restore_status(void *param)
 
347
{
 
348
  MI_INFO *info= (MI_INFO*) param;
 
349
  info->state= &info->s->state.state;
 
350
  info->append_insert_at_end= 0;
 
351
}
 
352
 
 
353
 
 
354
void mi_copy_status(void* to,void *from)
 
355
{
 
356
  ((MI_INFO*) to)->state= &((MI_INFO*) from)->save_state;
 
357
}
 
358
 
 
359
 
 
360
/*
 
361
  Check if should allow concurrent inserts
 
362
 
 
363
  IMPLEMENTATION
 
364
    Allow concurrent inserts if we don't have a hole in the table or
 
365
    if there is no active write lock and there is active read locks and 
 
366
    myisam_concurrent_insert == 2. In this last case the new
 
367
    row('s) are inserted at end of file instead of filling up the hole.
 
368
 
 
369
    The last case is to allow one to inserts into a heavily read-used table
 
370
    even if there is holes.
 
371
 
 
372
  NOTES
 
373
    If there is a an rtree indexes in the table, concurrent inserts are
 
374
    disabled in mi_open()
 
375
 
 
376
  RETURN
 
377
    0  ok to use concurrent inserts
 
378
    1  not ok
 
379
*/
 
380
 
 
381
my_bool mi_check_status(void *param)
 
382
{
 
383
  MI_INFO *info=(MI_INFO*) param;
 
384
  /*
 
385
    The test for w_locks == 1 is here because this thread has already done an
 
386
    external lock (in other words: w_locks == 1 means no other threads has
 
387
    a write lock)
 
388
  */
 
389
  DBUG_PRINT("info",("dellink: %ld  r_locks: %u  w_locks: %u",
 
390
                     (long) info->s->state.dellink, (uint) info->s->r_locks,
 
391
                     (uint) info->s->w_locks));
 
392
  return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
 
393
                     (myisam_concurrent_insert == 2 && info->s->r_locks &&
 
394
                      info->s->w_locks == 1));
 
395
}
 
396
 
 
397
 
 
398
/****************************************************************************
 
399
 ** functions to read / write the state
 
400
****************************************************************************/
 
401
 
 
402
int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
 
403
{
 
404
  DBUG_ENTER("_mi_readinfo");
 
405
 
 
406
  if (info->lock_type == F_UNLCK)
 
407
  {
 
408
    MYISAM_SHARE *share=info->s;
 
409
    if (!share->tot_locks)
 
410
    {
 
411
      if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
412
                  info->lock_wait | MY_SEEK_NOT_DONE))
 
413
        DBUG_RETURN(1);
 
414
      if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
 
415
      {
 
416
        int error=my_errno ? my_errno : -1;
 
417
        VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
 
418
                     MYF(MY_SEEK_NOT_DONE)));
 
419
        my_errno=error;
 
420
        DBUG_RETURN(1);
 
421
      }
 
422
    }
 
423
    if (check_keybuffer)
 
424
      VOID(_mi_test_if_changed(info));
 
425
    info->invalidator=info->s->invalidator;
 
426
  }
 
427
  else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
 
428
  {
 
429
    my_errno=EACCES;                            /* Not allowed to change */
 
430
    DBUG_RETURN(-1);                            /* when have read_lock() */
 
431
  }
 
432
  DBUG_RETURN(0);
 
433
} /* _mi_readinfo */
 
434
 
 
435
 
 
436
/*
 
437
  Every isam-function that uppdates the isam-database MUST end with this
 
438
  request
 
439
*/
 
440
 
 
441
int _mi_writeinfo(register MI_INFO *info, uint operation)
 
442
{
 
443
  int error,olderror;
 
444
  MYISAM_SHARE *share=info->s;
 
445
  DBUG_ENTER("_mi_writeinfo");
 
446
  DBUG_PRINT("info",("operation: %u  tot_locks: %u", operation,
 
447
                     share->tot_locks));
 
448
 
 
449
  error=0;
 
450
  if (share->tot_locks == 0)
 
451
  {
 
452
    olderror=my_errno;                  /* Remember last error */
 
453
    if (operation)
 
454
    {                                   /* Two threads can't be here */
 
455
      share->state.process= share->last_process=   share->this_process;
 
456
      share->state.unique=  info->last_unique=     info->this_unique;
 
457
      share->state.update_count= info->last_loop= ++info->this_loop;
 
458
      if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
 
459
        olderror=my_errno;
 
460
#ifdef __WIN__
 
461
      if (myisam_flush)
 
462
      {
 
463
        _commit(share->kfile);
 
464
        _commit(info->dfile);
 
465
      }
 
466
#endif
 
467
    }
 
468
    if (!(operation & WRITEINFO_NO_UNLOCK) &&
 
469
        my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
 
470
                MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
 
471
      DBUG_RETURN(1);
 
472
    my_errno=olderror;
 
473
  }
 
474
  else if (operation)
 
475
    share->changed= 1;                  /* Mark keyfile changed */
 
476
  DBUG_RETURN(error);
 
477
} /* _mi_writeinfo */
 
478
 
 
479
 
 
480
        /* Test if someone has changed the database */
 
481
        /* (Should be called after readinfo) */
 
482
 
 
483
int _mi_test_if_changed(register MI_INFO *info)
 
484
{
 
485
  MYISAM_SHARE *share=info->s;
 
486
  if (share->state.process != share->last_process ||
 
487
      share->state.unique  != info->last_unique ||
 
488
      share->state.update_count != info->last_loop)
 
489
  {                                             /* Keyfile has changed */
 
490
    DBUG_PRINT("info",("index file changed"));
 
491
    if (share->state.process != share->this_process)
 
492
      VOID(flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE));
 
493
    share->last_process=share->state.process;
 
494
    info->last_unique=  share->state.unique;
 
495
    info->last_loop=    share->state.update_count;
 
496
    info->update|=      HA_STATE_WRITTEN;       /* Must use file on next */
 
497
    info->data_changed= 1;                      /* For mi_is_changed */
 
498
    return 1;
 
499
  }
 
500
  return (!(info->update & HA_STATE_AKTIV) ||
 
501
          (info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED |
 
502
                           HA_STATE_KEY_CHANGED)));
 
503
} /* _mi_test_if_changed */
 
504
 
 
505
 
 
506
/*
 
507
  Put a mark in the .MYI file that someone is updating the table
 
508
 
 
509
 
 
510
  DOCUMENTATION
 
511
 
 
512
  state.open_count in the .MYI file is used the following way:
 
513
  - For the first change of the .MYI file in this process open_count is
 
514
    incremented by mi_mark_file_change(). (We have a write lock on the file
 
515
    when this happens)
 
516
  - In mi_close() it's decremented by _mi_decrement_open_count() if it
 
517
    was incremented in the same process.
 
518
 
 
519
  This mean that if we are the only process using the file, the open_count
 
520
  tells us if the MYISAM file wasn't properly closed. (This is true if
 
521
  my_disable_locking is set).
 
522
*/
 
523
 
 
524
 
 
525
int _mi_mark_file_changed(MI_INFO *info)
 
526
{
 
527
  uchar buff[3];
 
528
  register MYISAM_SHARE *share=info->s;
 
529
  DBUG_ENTER("_mi_mark_file_changed");
 
530
 
 
531
  if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
 
532
  {
 
533
    share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED |
 
534
                           STATE_NOT_OPTIMIZED_KEYS);
 
535
    if (!share->global_changed)
 
536
    {
 
537
      share->global_changed=1;
 
538
      share->state.open_count++;
 
539
    }
 
540
    if (!share->temporary)
 
541
    {
 
542
      mi_int2store(buff,share->state.open_count);
 
543
      buff[2]=1;                                /* Mark that it's changed */
 
544
      DBUG_RETURN(my_pwrite(share->kfile,buff,sizeof(buff),
 
545
                            sizeof(share->state.header),
 
546
                            MYF(MY_NABP)));
 
547
    }
 
548
  }
 
549
  DBUG_RETURN(0);
 
550
}
 
551
 
 
552
 
 
553
/*
 
554
  This is only called by close or by extra(HA_FLUSH) if the OS has the pwrite()
 
555
  call.  In these context the following code should be safe!
 
556
 */
 
557
 
 
558
int _mi_decrement_open_count(MI_INFO *info)
 
559
{
 
560
  uchar buff[2];
 
561
  register MYISAM_SHARE *share=info->s;
 
562
  int lock_error=0,write_error=0;
 
563
  if (share->global_changed)
 
564
  {
 
565
    uint old_lock=info->lock_type;
 
566
    share->global_changed=0;
 
567
    lock_error=mi_lock_database(info,F_WRLCK);
 
568
    /* Its not fatal even if we couldn't get the lock ! */
 
569
    if (share->state.open_count > 0)
 
570
    {
 
571
      share->state.open_count--;
 
572
      mi_int2store(buff,share->state.open_count);
 
573
      write_error=my_pwrite(share->kfile,buff,sizeof(buff),
 
574
                            sizeof(share->state.header),
 
575
                            MYF(MY_NABP));
 
576
    }
 
577
    if (!lock_error)
 
578
      lock_error=mi_lock_database(info,old_lock);
 
579
  }
 
580
  return test(lock_error || write_error);
 
581
}