~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/lock.cc

  • Committer: Monty Taylor
  • Date: 2009-12-21 04:32:56 UTC
  • mto: (1253.2.3 out-of-tree)
  • mto: This revision was merged to the branch mainline in revision 1250.
  • Revision ID: mordred@inaugust.com-20091221043256-n7ii7ynwsebr1r47
Removed things from server_includes.h.

Show diffs side-by-side

added added

removed removed

Lines of Context:
73
73
  we are forced to use mysql_lock_merge.
74
74
*/
75
75
#include <drizzled/server_includes.h>
 
76
#include <fcntl.h>
76
77
#include <drizzled/error.h>
77
78
#include <mysys/hash.h>
78
79
#include <mysys/thr_lock.h>
87
88
 
88
89
extern HASH open_cache;
89
90
 
90
 
/* flags for get_lock_data */
91
 
#define GET_LOCK_UNLOCK         1
92
 
#define GET_LOCK_STORE_LOCKS    2
93
 
 
94
91
static DRIZZLE_LOCK *get_lock_data(Session *session, Table **table,
95
92
                                   uint32_t count,
96
 
                                   uint32_t flags, Table **write_locked);
 
93
                                   bool should_lock, Table **write_locked);
97
94
static int lock_external(Session *session, Table **table,uint32_t count);
98
95
static int unlock_external(Session *session, Table **table,uint32_t count);
99
96
static void print_lock_error(int error, const char *);
166
163
 
167
164
 
168
165
DRIZZLE_LOCK *mysql_lock_tables(Session *session, Table **tables, uint32_t count,
169
 
                              uint32_t flags, bool *need_reopen)
 
166
                                uint32_t flags, bool *need_reopen)
170
167
{
171
168
  DRIZZLE_LOCK *sql_lock;
172
169
  Table *write_lock_used;
176
173
 
177
174
  for (;;)
178
175
  {
179
 
    if (! (sql_lock= get_lock_data(session, tables, count, GET_LOCK_STORE_LOCKS,
 
176
    if (! (sql_lock= get_lock_data(session, tables, count, true,
180
177
                                   &write_lock_used)))
181
178
      break;
182
179
 
243
240
    else if (!session->open_tables)
244
241
    {
245
242
      // Only using temporary tables, no need to unlock
246
 
      session->some_tables_deleted=0;
 
243
      session->some_tables_deleted= 0;
247
244
      break;
248
245
    }
249
246
    session->set_proc_info(0);
277
274
    if (sql_lock)
278
275
    {
279
276
      mysql_unlock_tables(session,sql_lock);
280
 
      sql_lock=0;
 
277
      sql_lock= NULL;
281
278
    }
282
279
  }
283
280
 
299
296
         (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
300
297
      lock_type=F_RDLCK;
301
298
 
302
 
    if ((error=(*tables)->file->ha_external_lock(session,lock_type)))
 
299
    if ((error=(*tables)->cursor->ha_external_lock(session,lock_type)))
303
300
    {
304
 
      print_lock_error(error, (*tables)->file->table_type());
 
301
      print_lock_error(error, (*tables)->cursor->engine->getName().c_str());
305
302
      while (--i)
306
303
      {
307
304
        tables--;
308
 
        (*tables)->file->ha_external_lock(session, F_UNLCK);
 
305
        (*tables)->cursor->ha_external_lock(session, F_UNLCK);
309
306
        (*tables)->current_lock=F_UNLCK;
310
307
      }
311
 
      return(error);
 
308
      return error;
312
309
    }
313
310
    else
314
311
    {
316
313
      (*tables)->current_lock= lock_type;
317
314
    }
318
315
  }
319
 
  return(0);
 
316
  return 0;
320
317
}
321
318
 
322
319
 
336
333
  This will work even if get_lock_data fails (next unlock will free all)
337
334
*/
338
335
 
339
 
void mysql_unlock_some_tables(Session *session, Table **table,uint32_t count)
 
336
void mysql_unlock_some_tables(Session *session, Table **table, uint32_t count)
340
337
{
341
338
  DRIZZLE_LOCK *sql_lock;
342
339
  Table *write_lock_used;
343
 
  if ((sql_lock= get_lock_data(session, table, count, GET_LOCK_UNLOCK,
 
340
  if ((sql_lock= get_lock_data(session, table, count, false,
344
341
                               &write_lock_used)))
345
342
    mysql_unlock_tables(session, sql_lock);
346
343
}
426
423
                          effect is desired.
427
424
*/
428
425
 
429
 
void mysql_lock_remove(Session *session, DRIZZLE_LOCK *locked,Table *table,
430
 
                       bool always_unlock)
431
 
{
432
 
  if (always_unlock == true)
433
 
    mysql_unlock_some_tables(session, &table, /* table count */ 1);
434
 
  if (locked)
435
 
  {
436
 
    register uint32_t i;
437
 
    for (i=0; i < locked->table_count; i++)
438
 
    {
439
 
      if (locked->table[i] == table)
440
 
      {
441
 
        uint32_t  j, removed_locks, old_tables;
442
 
        Table *tbl;
443
 
        uint32_t lock_data_end;
444
 
 
445
 
        assert(table->lock_position == i);
446
 
 
447
 
        /* Unlock if not yet unlocked */
448
 
        if (always_unlock == false)
449
 
          mysql_unlock_some_tables(session, &table, /* table count */ 1);
450
 
 
451
 
        /* Decrement table_count in advance, making below expressions easier */
452
 
        old_tables= --locked->table_count;
453
 
 
454
 
        /* The table has 'removed_locks' lock data elements in locked->locks */
455
 
        removed_locks= table->lock_count;
456
 
 
457
 
        /* Move down all table pointers above 'i'. */
458
 
        memmove((locked->table+i), (locked->table+i+1),
459
 
                (old_tables - i) * sizeof(Table*));
460
 
 
461
 
        lock_data_end= table->lock_data_start + table->lock_count;
462
 
        /* Move down all lock data pointers above 'table->lock_data_end-1' */
463
 
        memmove((locked->locks + table->lock_data_start),
464
 
                (locked->locks + lock_data_end),
465
 
                (locked->lock_count - lock_data_end) *
466
 
                sizeof(THR_LOCK_DATA*));
467
 
 
468
 
        /*
469
 
          Fix moved table elements.
470
 
          lock_position is the index in the 'locked->table' array,
471
 
          it must be fixed by one.
472
 
          table->lock_data_start is pointer to the lock data for this table
473
 
          in the 'locked->locks' array, they must be fixed by 'removed_locks',
474
 
          the lock data count of the removed table.
475
 
        */
476
 
        for (j= i ; j < old_tables; j++)
477
 
        {
478
 
          tbl= locked->table[j];
479
 
          tbl->lock_position--;
480
 
          assert(tbl->lock_position == j);
481
 
          tbl->lock_data_start-= removed_locks;
482
 
        }
483
 
 
484
 
        /* Finally adjust lock_count. */
485
 
        locked->lock_count-= removed_locks;
486
 
        break;
487
 
      }
488
 
    }
489
 
  }
490
 
}
491
 
 
492
 
/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
493
 
 
494
 
void mysql_lock_downgrade_write(Session *session, Table *table,
495
 
                                thr_lock_type new_lock_type)
496
 
{
497
 
  DRIZZLE_LOCK *locked;
498
 
  Table *write_lock_used;
499
 
  if ((locked = get_lock_data(session, &table, 1, GET_LOCK_UNLOCK,
500
 
                              &write_lock_used)))
501
 
  {
502
 
    for (uint32_t i=0; i < locked->lock_count; i++)
503
 
      thr_downgrade_write_lock(locked->locks[i], new_lock_type);
504
 
    free((unsigned char*) locked);
505
 
  }
 
426
void mysql_lock_remove(Session *session, Table *table)
 
427
{
 
428
  mysql_unlock_some_tables(session, &table, /* table count */ 1);
506
429
}
507
430
 
508
431
 
509
432
/** Abort all other threads waiting to get lock in table. */
510
433
 
511
 
void mysql_lock_abort(Session *session, Table *table, bool upgrade_lock)
 
434
void mysql_lock_abort(Session *session, Table *table)
512
435
{
513
436
  DRIZZLE_LOCK *locked;
514
437
  Table *write_lock_used;
515
438
 
516
 
  if ((locked= get_lock_data(session, &table, 1, GET_LOCK_UNLOCK,
 
439
  if ((locked= get_lock_data(session, &table, 1, false,
517
440
                             &write_lock_used)))
518
441
  {
519
 
    for (uint32_t i=0; i < locked->lock_count; i++)
520
 
      thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
 
442
    for (uint32_t x= 0; x < locked->lock_count; x++)
 
443
      thr_abort_locks(locked->locks[x]->lock);
521
444
    free((unsigned char*) locked);
522
445
  }
523
 
  return;
524
446
}
525
447
 
526
448
 
542
464
  Table *write_lock_used;
543
465
  bool result= false;
544
466
 
545
 
  if ((locked= get_lock_data(session, &table, 1, GET_LOCK_UNLOCK,
 
467
  if ((locked= get_lock_data(session, &table, 1, false,
546
468
                             &write_lock_used)))
547
469
  {
548
470
    for (uint32_t i=0; i < locked->lock_count; i++)
553
475
    }
554
476
    free((unsigned char*) locked);
555
477
  }
556
 
  return(result);
557
 
}
558
 
 
559
 
 
560
 
DRIZZLE_LOCK *mysql_lock_merge(DRIZZLE_LOCK *a,DRIZZLE_LOCK *b)
561
 
{
562
 
  DRIZZLE_LOCK *sql_lock;
563
 
  Table **table, **end_table;
564
 
 
565
 
  if (!(sql_lock= (DRIZZLE_LOCK*)
566
 
        malloc(sizeof(*sql_lock)+
567
 
               sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
568
 
               sizeof(Table*)*(a->table_count+b->table_count))))
569
 
    return(0);                          // Fatal error
570
 
  sql_lock->lock_count=a->lock_count+b->lock_count;
571
 
  sql_lock->table_count=a->table_count+b->table_count;
572
 
  sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
573
 
  sql_lock->table=(Table**) (sql_lock->locks+sql_lock->lock_count);
574
 
  memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
575
 
  memcpy(sql_lock->locks+a->lock_count,b->locks,
576
 
         b->lock_count*sizeof(*b->locks));
577
 
  memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
578
 
  memcpy(sql_lock->table+a->table_count,b->table,
579
 
         b->table_count*sizeof(*b->table));
580
 
 
581
 
  /*
582
 
    Now adjust lock_position and lock_data_start for all objects that was
583
 
    moved in 'b' (as there is now all objects in 'a' before these).
584
 
  */
585
 
  for (table= sql_lock->table + a->table_count,
586
 
         end_table= table + b->table_count;
587
 
       table < end_table;
588
 
       table++)
589
 
  {
590
 
    (*table)->lock_position+=   a->table_count;
591
 
    (*table)->lock_data_start+= a->lock_count;
592
 
  }
593
 
 
594
 
  /* Delete old, not needed locks */
595
 
  free((unsigned char*) a);
596
 
  free((unsigned char*) b);
597
 
  return(sql_lock);
598
 
}
599
 
 
600
 
 
601
 
/**
602
 
  Find duplicate lock in tables.
603
 
 
604
 
  Temporary tables are ignored here like they are ignored in
605
 
  get_lock_data(). If we allow two opens on temporary tables later,
606
 
  both functions should be checked.
607
 
 
608
 
  @param session                 The current thread.
609
 
  @param needle              The table to check for duplicate lock.
610
 
  @param haystack            The list of tables to search for the dup lock.
611
 
 
612
 
  @note
613
 
    This is mainly meant for MERGE tables in INSERT ... SELECT
614
 
    situations. The 'real', underlying tables can be found only after
615
 
    the MERGE tables are opened. This function assumes that the tables are
616
 
    already locked.
617
 
 
618
 
  @retval
619
 
    NULL    No duplicate lock found.
620
 
  @retval
621
 
    !NULL   First table from 'haystack' that matches a lock on 'needle'.
622
 
*/
623
 
 
624
 
TableList *mysql_lock_have_duplicate(Session *session, TableList *needle,
625
 
                                      TableList *haystack)
626
 
{
627
 
  DRIZZLE_LOCK            *mylock;
628
 
  Table                 **lock_tables;
629
 
  Table                 *table;
630
 
  Table                 *table2;
631
 
  THR_LOCK_DATA         **lock_locks;
632
 
  THR_LOCK_DATA         **table_lock_data;
633
 
  THR_LOCK_DATA         **end_data;
634
 
  THR_LOCK_DATA         **lock_data2;
635
 
  THR_LOCK_DATA         **end_data2;
636
 
 
637
 
  /*
638
 
    Table may not be defined for derived or view tables.
639
 
    Table may not be part of a lock for delayed operations.
640
 
  */
641
 
  if (! (table= needle->table) || ! table->lock_count)
642
 
    goto end;
643
 
 
644
 
  /* A temporary table does not have locks. */
645
 
  if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
646
 
    goto end;
647
 
 
648
 
  /* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
649
 
  if (! (mylock= session->lock ? session->lock : session->locked_tables))
650
 
    goto end;
651
 
 
652
 
  /* If we have less than two tables, we cannot have duplicates. */
653
 
  if (mylock->table_count < 2)
654
 
    goto end;
655
 
 
656
 
  lock_locks=  mylock->locks;
657
 
  lock_tables= mylock->table;
658
 
 
659
 
  /* Prepare table related variables that don't change in loop. */
660
 
  assert((table->lock_position < mylock->table_count) &&
661
 
              (table == lock_tables[table->lock_position]));
662
 
  table_lock_data= lock_locks + table->lock_data_start;
663
 
  end_data= table_lock_data + table->lock_count;
664
 
 
665
 
  for (; haystack; haystack= haystack->next_global)
666
 
  {
667
 
    if (haystack->placeholder())
668
 
      continue;
669
 
    table2= haystack->table;
670
 
    if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
671
 
      continue;
672
 
 
673
 
    /* All tables in list must be in lock. */
674
 
    assert((table2->lock_position < mylock->table_count) &&
675
 
                (table2 == lock_tables[table2->lock_position]));
676
 
 
677
 
    for (lock_data2=  lock_locks + table2->lock_data_start,
678
 
           end_data2= lock_data2 + table2->lock_count;
679
 
         lock_data2 < end_data2;
680
 
         lock_data2++)
681
 
    {
682
 
      THR_LOCK_DATA **lock_data;
683
 
      THR_LOCK *lock2= (*lock_data2)->lock;
684
 
 
685
 
      for (lock_data= table_lock_data;
686
 
           lock_data < end_data;
687
 
           lock_data++)
688
 
      {
689
 
        if ((*lock_data)->lock == lock2)
690
 
        {
691
 
          return(haystack);
692
 
        }
693
 
      }
694
 
    }
695
 
  }
696
 
 
697
 
 end:
698
 
  return(NULL);
 
478
  return result;
699
479
}
700
480
 
701
481
 
711
491
    if ((*table)->current_lock != F_UNLCK)
712
492
    {
713
493
      (*table)->current_lock = F_UNLCK;
714
 
      if ((error=(*table)->file->ha_external_lock(session, F_UNLCK)))
 
494
      if ((error=(*table)->cursor->ha_external_lock(session, F_UNLCK)))
715
495
      {
716
496
        error_code=error;
717
 
        print_lock_error(error_code, (*table)->file->table_type());
 
497
        print_lock_error(error_code, (*table)->cursor->engine->getName().c_str());
718
498
      }
719
499
    }
720
500
    table++;
721
501
  } while (--count);
722
 
  return(error_code);
 
502
  return error_code;
723
503
}
724
504
 
725
505
 
728
508
 
729
509
  @param session                    Thread handler
730
510
  @param table_ptr          Pointer to tables that should be locks
731
 
  @param flags              One of:
732
 
           - GET_LOCK_UNLOCK      : If we should send TL_IGNORE to store lock
733
 
           - GET_LOCK_STORE_LOCKS : Store lock info in Table
 
511
  @param should_lock                One of:
 
512
           - false      : If we should send TL_IGNORE to store lock
 
513
           - true       : Store lock info in Table
734
514
  @param write_lock_used   Store pointer to last table with WRITE_ALLOW_WRITE
735
515
*/
736
516
 
737
517
static DRIZZLE_LOCK *get_lock_data(Session *session, Table **table_ptr, uint32_t count,
738
 
                                 uint32_t flags, Table **write_lock_used)
 
518
                                 bool should_lock, Table **write_lock_used)
739
519
{
740
520
  uint32_t i,tables,lock_count;
741
521
  DRIZZLE_LOCK *sql_lock;
742
522
  THR_LOCK_DATA **locks, **locks_buf, **locks_start;
743
523
  Table **to, **table_buf;
744
524
 
745
 
  assert((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS));
746
 
 
747
525
  *write_lock_used=0;
748
 
  for (i=tables=lock_count=0 ; i < count ; i++)
 
526
  for (i= tables= lock_count= 0 ; i < count ; i++)
749
527
  {
750
528
    Table *t= table_ptr[i];
751
529
 
752
 
    if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
 
530
    if (! (t->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK)))
753
531
    {
754
 
      tables+= t->file->lock_count();
 
532
      tables++;
755
533
      lock_count++;
756
534
    }
757
535
  }
766
544
        malloc(sizeof(*sql_lock) +
767
545
               sizeof(THR_LOCK_DATA*) * tables * 2 +
768
546
               sizeof(table_ptr) * lock_count)))
769
 
    return(0);
 
547
    return NULL;
770
548
  locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
771
549
  to= table_buf= sql_lock->table= (Table**) (locks + tables * 2);
772
 
  sql_lock->table_count=lock_count;
 
550
  sql_lock->table_count= lock_count;
773
551
 
774
552
  for (i=0 ; i < count ; i++)
775
553
  {
776
554
    Table *table;
777
555
    enum thr_lock_type lock_type;
778
556
 
779
 
    if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
 
557
    if (table_ptr[i]->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK))
780
558
      continue;
 
559
 
 
560
    table= table_ptr[i];
781
561
    lock_type= table->reginfo.lock_type;
782
562
    assert (lock_type != TL_WRITE_DEFAULT);
783
563
    if (lock_type >= TL_WRITE_ALLOW_WRITE)
789
569
        /* Clear the lock type of the lock data that are stored already. */
790
570
        sql_lock->lock_count= locks - sql_lock->locks;
791
571
        reset_lock_data_and_free(&sql_lock);
792
 
        return(0);
 
572
        return NULL;
793
573
      }
794
574
    }
795
575
    locks_start= locks;
796
 
    locks= table->file->store_lock(session, locks,
797
 
                                   (flags & GET_LOCK_UNLOCK) ? TL_IGNORE :
798
 
                                   lock_type);
799
 
    if (flags & GET_LOCK_STORE_LOCKS)
 
576
    locks= table->cursor->store_lock(session, locks,
 
577
                                   should_lock == false ? TL_IGNORE : lock_type);
 
578
    if (should_lock)
800
579
    {
801
580
      table->lock_position=   (uint32_t) (to - table_buf);
802
581
      table->lock_data_start= (uint32_t) (locks_start - locks_buf);
803
582
      table->lock_count=      (uint32_t) (locks - locks_start);
 
583
      assert(table->lock_count == 1);
804
584
    }
805
585
    *to++= table;
806
586
  }
819
599
    And in the FLUSH case, the memory is released quickly anyway.
820
600
  */
821
601
  sql_lock->lock_count= locks - locks_buf;
822
 
  return(sql_lock);
823
 
}
824
 
 
825
 
 
826
 
/*****************************************************************************
827
 
  Lock table based on the name.
828
 
  This is used when we need total access to a closed, not open table
829
 
*****************************************************************************/
830
 
 
831
 
/**
832
 
  Lock and wait for the named lock.
833
 
 
834
 
  @param session                        Thread handler
835
 
  @param table_list             Lock first table in this list
836
 
 
837
 
 
838
 
  @note
839
 
    Works together with global read lock.
840
 
 
841
 
  @retval
842
 
    0   ok
843
 
  @retval
844
 
    1   error
845
 
*/
846
 
 
847
 
int lock_and_wait_for_table_name(Session *session, TableList *table_list)
848
 
{
849
 
  int lock_retcode;
850
 
  int error= -1;
851
 
 
852
 
  if (wait_if_global_read_lock(session, 0, 1))
853
 
    return(1);
854
 
  pthread_mutex_lock(&LOCK_open);
855
 
  if ((lock_retcode = lock_table_name(session, table_list, true)) < 0)
856
 
    goto end;
857
 
  if (lock_retcode && wait_for_locked_table_names(session, table_list))
858
 
  {
859
 
    unlock_table_name(session, table_list);
860
 
    goto end;
861
 
  }
862
 
  error=0;
863
 
 
864
 
end:
865
 
  pthread_mutex_unlock(&LOCK_open);
866
 
  start_waiting_global_read_lock(session);
867
 
  return(error);
 
602
 
 
603
  return sql_lock;
868
604
}
869
605
 
870
606
 
880
616
 
881
617
  @warning
882
618
    If you are going to update the table, you should use
883
 
    lock_and_wait_for_table_name instead of this function as this works
 
619
    lock_and_wait_for_table_name(removed) instead of this function as this works
884
620
    together with 'FLUSH TABLES WITH READ LOCK'
885
621
 
886
622
  @note
904
640
  bool  found_locked_table= false;
905
641
  HASH_SEARCH_STATE state;
906
642
 
907
 
  key_length= create_table_def_key(session, key, table_list, 0);
 
643
  key_length= table_list->create_table_def_key(key);
908
644
 
909
645
  if (check_in_use)
910
646
  {
926
662
      {
927
663
        table->s->version= 0;                  // Ensure no one can use this
928
664
        table->locked_by_name= 1;
929
 
        return(0);
 
665
        return 0;
930
666
      }
931
667
    }
932
668
  }
933
669
 
934
 
  if (session->locked_tables && session->locked_tables->table_count &&
935
 
      ! find_temporary_table(session, table_list->db, table_list->table_name))
936
 
  {
937
 
    if (found_locked_table)
938
 
      my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->alias);
939
 
    else
940
 
      my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_list->alias);
941
 
 
942
 
    return(-1);
943
 
  }
944
 
 
945
 
  if (!(table= table_cache_insert_placeholder(session, key, key_length)))
946
 
    return(-1);
 
670
  if (!(table= session->table_cache_insert_placeholder(key, key_length)))
 
671
    return -1;
947
672
 
948
673
  table_list->table=table;
949
674
 
953
678
}
954
679
 
955
680
 
956
 
void unlock_table_name(Session *,
957
 
                       TableList *table_list)
 
681
void unlock_table_name(TableList *table_list)
958
682
{
959
683
  if (table_list->table)
960
684
  {
964
688
}
965
689
 
966
690
 
967
 
static bool locked_named_table(Session *,
968
 
                               TableList *table_list)
 
691
static bool locked_named_table(TableList *table_list)
969
692
{
970
693
  for (; table_list ; table_list=table_list->next_local)
971
694
  {
987
710
 
988
711
bool wait_for_locked_table_names(Session *session, TableList *table_list)
989
712
{
990
 
  bool result=0;
 
713
  bool result= false;
991
714
 
992
715
  safe_mutex_assert_owner(&LOCK_open);
993
716
 
994
 
  while (locked_named_table(session,table_list))
 
717
  while (locked_named_table(table_list))
995
718
  {
996
719
    if (session->killed)
997
720
    {
998
721
      result=1;
999
722
      break;
1000
723
    }
1001
 
    wait_for_condition(session, &LOCK_open, &COND_refresh);
1002
 
    pthread_mutex_lock(&LOCK_open);
 
724
    session->wait_for_condition(&LOCK_open, &COND_refresh);
 
725
    pthread_mutex_lock(&LOCK_open); /* Wait for a table to unlock and then lock it */
1003
726
  }
1004
 
  return(result);
 
727
  return result;
1005
728
}
1006
729
 
1007
730
 
1011
734
  REQUIREMENTS
1012
735
  - One must have a lock on LOCK_open when calling this
1013
736
 
1014
 
  @param session                        Thread handle
1015
737
  @param table_list             Names of tables to lock
1016
738
 
1017
 
  @note
1018
 
    If you are just locking one table, you should use
1019
 
    lock_and_wait_for_table_name().
1020
 
 
1021
739
  @retval
1022
740
    0   ok
1023
741
  @retval
1032
750
  for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
1033
751
  {
1034
752
    int got_lock;
1035
 
    if ((got_lock=lock_table_name(session,lock_table, true)) < 0)
 
753
    if ((got_lock= lock_table_name(session,lock_table, true)) < 0)
1036
754
      goto end;                                 // Fatal error
1037
755
    if (got_lock)
1038
756
      got_all_locks=0;                          // Someone is using table
1041
759
  /* If some table was in use, wait until we got the lock */
1042
760
  if (!got_all_locks && wait_for_locked_table_names(session, table_list))
1043
761
    goto end;
1044
 
  return 0;
 
762
  return false;
1045
763
 
1046
764
end:
1047
 
  unlock_table_names(session, table_list, lock_table);
1048
 
  return 1;
 
765
  unlock_table_names(table_list, lock_table);
 
766
 
 
767
  return true;
1049
768
}
1050
769
 
1051
770
 
1086
805
 
1087
806
 
1088
807
/**
1089
 
  Test is 'table' is protected by an exclusive name lock.
1090
 
 
1091
 
  @param[in] session        The current thread handler
1092
 
  @param[in] table_list Table container containing the single table to be
1093
 
                        tested
1094
 
 
1095
 
  @note Needs to be protected by LOCK_open mutex.
1096
 
 
1097
 
  @return Error status code
1098
 
    @retval TRUE Table is protected
1099
 
    @retval FALSE Table is not protected
1100
 
*/
1101
 
 
1102
 
bool
1103
 
is_table_name_exclusively_locked_by_this_thread(Session *session,
1104
 
                                                TableList *table_list)
1105
 
{
1106
 
  char  key[MAX_DBKEY_LENGTH];
1107
 
  uint32_t  key_length;
1108
 
 
1109
 
  key_length= create_table_def_key(session, key, table_list, 0);
1110
 
 
1111
 
  return is_table_name_exclusively_locked_by_this_thread(session, (unsigned char *)key,
1112
 
                                                         key_length);
1113
 
}
1114
 
 
1115
 
 
1116
 
/**
1117
 
  Test is 'table key' is protected by an exclusive name lock.
1118
 
 
1119
 
  @param[in] session        The current thread handler.
1120
 
  @param[in] key
1121
 
  @param[in] key_length
1122
 
 
1123
 
  @note Needs to be protected by LOCK_open mutex
1124
 
 
1125
 
  @retval TRUE Table is protected
1126
 
  @retval FALSE Table is not protected
1127
 
 */
1128
 
 
1129
 
bool
1130
 
is_table_name_exclusively_locked_by_this_thread(Session *session, unsigned char *key,
1131
 
                                                int key_length)
1132
 
{
1133
 
  HASH_SEARCH_STATE state;
1134
 
  Table *table;
1135
 
 
1136
 
  for (table= (Table*) hash_first(&open_cache, key,
1137
 
                                  key_length, &state);
1138
 
       table ;
1139
 
       table= (Table*) hash_next(&open_cache, key,
1140
 
                                 key_length, &state))
1141
 
  {
1142
 
    if (table->in_use == session &&
1143
 
        table->open_placeholder == 1 &&
1144
 
        table->s->version == 0)
1145
 
      return true;
1146
 
  }
1147
 
 
1148
 
  return false;
1149
 
}
1150
 
 
1151
 
/**
1152
808
  Unlock all tables in list with a name lock.
1153
809
 
1154
810
  @param
1155
 
    session                     Thread handle
1156
 
  @param
1157
811
    table_list          Names of tables to unlock
1158
812
  @param
1159
813
    last_table          Don't unlock any tables after this one.
1172
826
    1   Fatal error (end of memory ?)
1173
827
*/
1174
828
 
1175
 
void unlock_table_names(Session *session, TableList *table_list,
1176
 
                        TableList *last_table)
 
829
void unlock_table_names(TableList *table_list, TableList *last_table)
1177
830
{
1178
831
  for (TableList *table= table_list;
1179
832
       table != last_table;
1180
833
       table= table->next_local)
1181
 
    unlock_table_name(session,table);
 
834
    unlock_table_name(table);
1182
835
  broadcast_refresh();
1183
 
  return;
1184
836
}
1185
837
 
1186
838
 
1210
862
    my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), table);
1211
863
  else
1212
864
    my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), error);
1213
 
 
1214
 
  return;
1215
865
}
1216
866
 
1217
867
 
1314
964
    if (session->killed)
1315
965
    {
1316
966
      session->exit_cond(old_message);
1317
 
      return(1);
 
967
      return true;
1318
968
    }
1319
969
    session->global_read_lock= GOT_GLOBAL_READ_LOCK;
1320
970
    global_read_lock++;
1328
978
    forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
1329
979
    UPDATE and one does FLUSH TABLES WITH READ LOCK).
1330
980
  */
1331
 
  return(0);
 
981
  return false;
1332
982
}
1333
983
 
1334
984
 
1347
997
    pthread_cond_broadcast(&COND_global_read_lock);
1348
998
  }
1349
999
  session->global_read_lock= 0;
1350
 
 
1351
 
  return;
1352
1000
}
1353
1001
 
1354
1002
#define must_wait (global_read_lock &&                             \
1382
1030
        This allowance is needed to not break existing versions of innobackup
1383
1031
        which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT.
1384
1032
      */
1385
 
      return(is_not_commit);
 
1033
      return is_not_commit;
1386
1034
    }
1387
1035
    old_message=session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1388
1036
                                "Waiting for release of readlock");
1404
1052
    session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1405
1053
  else
1406
1054
    pthread_mutex_unlock(&LOCK_global_read_lock);
1407
 
  return(result);
 
1055
  return result;
1408
1056
}
1409
1057
 
1410
1058
 
1432
1080
    make_global_read_lock_block_commit(), do nothing.
1433
1081
  */
1434
1082
  if (session->global_read_lock != GOT_GLOBAL_READ_LOCK)
1435
 
    return(0);
 
1083
    return false;
1436
1084
  pthread_mutex_lock(&LOCK_global_read_lock);
1437
1085
  /* increment this BEFORE waiting on cond (otherwise race cond) */
1438
1086
  global_read_lock_blocks_commit++;
1445
1093
  else
1446
1094
    session->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
1447
1095
  session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1448
 
  return(error);
 
1096
  return error;
1449
1097
}
1450
1098
 
1451
1099
 
1475
1123
}
1476
1124
 
1477
1125
 
1478
 
/*
1479
 
  Try to get transactional table locks for the tables in the list.
1480
 
 
1481
 
  SYNOPSIS
1482
 
    try_transactional_lock()
1483
 
      session                       Thread handle
1484
 
      table_list                List of tables to lock
1485
 
 
1486
 
  DESCRIPTION
1487
 
    This is called if transactional table locks are requested for all
1488
 
    tables in table_list and no non-transactional locks pre-exist.
1489
 
 
1490
 
  RETURN
1491
 
    0                   OK. All tables are transactional locked.
1492
 
    1                   Error: must fall back to non-transactional locks.
1493
 
    -1                  Error: no recovery possible.
1494
 
*/
1495
 
 
1496
 
int try_transactional_lock(Session *session, TableList *table_list)
1497
 
{
1498
 
  uint32_t          dummy_counter;
1499
 
  int           error;
1500
 
  int           result= 0;
1501
 
 
1502
 
  /* Need to open the tables to be able to access engine methods. */
1503
 
  if (open_tables(session, &table_list, &dummy_counter, 0))
1504
 
  {
1505
 
    /* purecov: begin tested */
1506
 
    return(-1);
1507
 
    /* purecov: end */
1508
 
  }
1509
 
 
1510
 
  /* Required by InnoDB. */
1511
 
  session->in_lock_tables= true;
1512
 
 
1513
 
  if ((error= set_handler_table_locks(session, table_list, true)))
1514
 
  {
1515
 
    /*
1516
 
      Not all transactional locks could be taken. If the error was
1517
 
      something else but "unsupported by storage engine", abort the
1518
 
      execution of this statement.
1519
 
    */
1520
 
    if (error != HA_ERR_WRONG_COMMAND)
1521
 
    {
1522
 
      result= -1;
1523
 
      goto err;
1524
 
    }
1525
 
    /*
1526
 
      Fall back to non-transactional locks because transactional locks
1527
 
      are unsupported by a storage engine. No need to unlock the
1528
 
      successfully taken transactional locks. They go away at end of
1529
 
      transaction anyway.
1530
 
    */
1531
 
    result= 1;
1532
 
  }
1533
 
 
1534
 
 err:
1535
 
  /* We need to explicitly commit if autocommit mode is active. */
1536
 
  (void) ha_autocommit_or_rollback(session, 0);
1537
 
  /* Close the tables. The locks (if taken) persist in the storage engines. */
1538
 
  close_tables_for_reopen(session, &table_list);
1539
 
  session->in_lock_tables= false;
1540
 
  return(result);
1541
 
}
1542
 
 
1543
 
 
1544
 
/*
1545
 
  Check if lock method conversion was done and was allowed.
1546
 
 
1547
 
  SYNOPSIS
1548
 
    check_transactional_lock()
1549
 
      session                       Thread handle
1550
 
      table_list                List of tables to lock
1551
 
 
1552
 
  DESCRIPTION
1553
 
 
1554
 
    Lock method conversion can be done during parsing if one of the
1555
 
    locks is non-transactional. It can also happen if non-transactional
1556
 
    table locks exist when the statement is executed or if a storage
1557
 
    engine does not support transactional table locks.
1558
 
 
1559
 
    Check if transactional table locks have been converted to
1560
 
    non-transactional and if this was allowed. In a running transaction
1561
 
    or in strict mode lock method conversion is not allowed - report an
1562
 
    error. Otherwise it is allowed - issue a warning.
1563
 
 
1564
 
  RETURN
1565
 
    0                   OK. Proceed with non-transactional locks.
1566
 
    -1                  Error: Lock conversion is prohibited.
1567
 
*/
1568
 
 
1569
 
int check_transactional_lock(Session *, TableList *table_list)
1570
 
{
1571
 
  TableList    *tlist;
1572
 
  int           result= 0;
1573
 
 
1574
 
  for (tlist= table_list; tlist; tlist= tlist->next_global)
1575
 
  {
1576
 
 
1577
 
    /*
1578
 
      Unfortunately we cannot use tlist->placeholder() here. This method
1579
 
      returns TRUE if the table is not open, which is always the case
1580
 
      here. Whenever the definition of TableList::placeholder() is
1581
 
      changed, probably this condition needs to be changed too.
1582
 
    */
1583
 
    if (tlist->derived || tlist->schema_table || !tlist->lock_transactional)
1584
 
    {
1585
 
      continue;
1586
 
    }
1587
 
 
1588
 
    /* We must not convert the lock method in strict mode. */
1589
 
    {
1590
 
      my_error(ER_NO_AUTO_CONVERT_LOCK_STRICT, MYF(0),
1591
 
               tlist->alias ? tlist->alias : tlist->table_name);
1592
 
      result= -1;
1593
 
      continue;
1594
 
    }
1595
 
 
1596
 
  }
1597
 
 
1598
 
  return(result);
1599
 
}
1600
 
 
1601
 
 
1602
 
/*
1603
 
  Set table locks in the table handler.
1604
 
 
1605
 
  SYNOPSIS
1606
 
    set_handler_table_locks()
1607
 
      session                       Thread handle
1608
 
      table_list                List of tables to lock
1609
 
      transactional             If to lock transactional or non-transactional
1610
 
 
1611
 
  RETURN
1612
 
    0                   OK.
1613
 
    != 0                Error code from handler::lock_table().
1614
 
*/
1615
 
 
1616
 
int set_handler_table_locks(Session *session, TableList *table_list,
1617
 
                            bool transactional)
1618
 
{
1619
 
  TableList    *tlist;
1620
 
  int           error= 0;
1621
 
 
1622
 
  for (tlist= table_list; tlist; tlist= tlist->next_global)
1623
 
  {
1624
 
    int lock_type;
1625
 
    int lock_timeout= -1; /* Use default for non-transactional locks. */
1626
 
 
1627
 
    if (tlist->placeholder())
1628
 
      continue;
1629
 
 
1630
 
    assert((tlist->lock_type == TL_READ) ||
1631
 
                (tlist->lock_type == TL_READ_NO_INSERT) ||
1632
 
                (tlist->lock_type == TL_WRITE_DEFAULT) ||
1633
 
                (tlist->lock_type == TL_WRITE) ||
1634
 
                (tlist->lock_type == TL_WRITE_LOW_PRIORITY));
1635
 
 
1636
 
    /*
1637
 
      Every tlist object has a proper lock_type set. Even if it came in
1638
 
      the list as a base table from a view only.
1639
 
    */
1640
 
    lock_type= ((tlist->lock_type <= TL_READ_NO_INSERT) ?
1641
 
                HA_LOCK_IN_SHARE_MODE : HA_LOCK_IN_EXCLUSIVE_MODE);
1642
 
 
1643
 
    if (transactional)
1644
 
    {
1645
 
      /*
1646
 
        The lock timeout is not set if this table belongs to a view. We
1647
 
        need to take it from the top-level view. After this loop
1648
 
        iteration, lock_timeout is not needed any more. Not even if the
1649
 
        locks are converted to non-transactional locks later.
1650
 
        Non-transactional locks do not support a lock_timeout.
1651
 
      */
1652
 
      lock_timeout= tlist->top_table()->lock_timeout;
1653
 
 
1654
 
      /*
1655
 
        For warning/error reporting we need to set the intended lock
1656
 
        method in the TableList object. It will be used later by
1657
 
        check_transactional_lock(). The lock method is not set if this
1658
 
        table belongs to a view. We can safely set it to transactional
1659
 
        locking here. Even for non-view tables. This function is not
1660
 
        called if non-transactional locking was requested for any
1661
 
        object.
1662
 
      */
1663
 
      tlist->lock_transactional= true;
1664
 
    }
1665
 
 
1666
 
    /*
1667
 
      Because we need to set the lock method (see above) for all
1668
 
      involved tables, we cannot break the loop on an error.
1669
 
      But we do not try more locks after the first error.
1670
 
      However, for non-transactional locking handler::lock_table() is
1671
 
      a hint only. So we continue to call it for other tables.
1672
 
    */
1673
 
    if (!error || !transactional)
1674
 
    {
1675
 
      error= tlist->table->file->lock_table(session, lock_type, lock_timeout);
1676
 
      if (error && transactional && (error != HA_ERR_WRONG_COMMAND))
1677
 
        tlist->table->file->print_error(error, MYF(0));
1678
 
    }
1679
 
  }
1680
 
 
1681
 
  return(error);
1682
 
}
1683
 
 
1684
 
 
1685
1126
/**
1686
1127
  @} (end of group Locking)
1687
1128
*/