~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/locking/global.cc

  • Committer: Lee Bieber
  • Date: 2010-11-20 01:33:21 UTC
  • mfrom: (1878.10.4 drizzle_bug665252)
  • Revision ID: kalebral@gmail.com-20101120013321-7nk9lq4nnr20zk6b
Merge Billy - removed my_getsysdate, my_micro_time and my_micro_time_and_time and replaced with boost::date_time for compatibility.

Show diffs side-by-side

added added

removed removed

Lines of Context:
163
163
  *mysql_lock= 0;
164
164
}
165
165
 
 
166
void DrizzleLock::reset(void)
 
167
{
 
168
  for (std::vector<THR_LOCK_DATA *>::iterator iter= locks.begin(); iter != locks.end(); iter++)
 
169
  {
 
170
    (*iter)->type= TL_UNLOCK;
 
171
  }
 
172
}
 
173
 
 
174
 
166
175
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags, bool *need_reopen)
167
176
{
168
177
  DrizzleLock *sql_lock;
204
213
     * Here, we advise all storage engines involved in the
205
214
     * statement that we are starting a new statement
206
215
     */
207
 
    if (sql_lock->sizeTable())
 
216
    if (sql_lock->table_count)
208
217
    {
209
 
      size_t num_tables= sql_lock->sizeTable();
 
218
      size_t num_tables= sql_lock->table_count;
210
219
      plugin::StorageEngine *engine;
211
220
      set<size_t> involved_slots;
212
221
      for (size_t x= 1; x <= num_tables; x++, tables++)
230
239
     * of the type of lock that Drizzle intends to take on a 
231
240
     * specific table.
232
241
     */
233
 
    if (sql_lock->sizeTable() && lock_external(sql_lock->getTable(), sql_lock->sizeTable()))
 
242
    if (sql_lock->table_count && lock_external(sql_lock->getTable(), sql_lock->table_count))
234
243
    {
235
244
      /* Clear the lock type of all lock data to avoid reusage. */
236
245
      reset_lock_data_and_free(&sql_lock);
238
247
    }
239
248
    set_proc_info("Table lock");
240
249
    /* Copy the lock data array. thr_multi_lock() reorders its contens. */
241
 
    memcpy(sql_lock->getLocks() + sql_lock->sizeLock(),
 
250
    memcpy(sql_lock->getLocks() + sql_lock->lock_count,
242
251
           sql_lock->getLocks(),
243
 
           sql_lock->sizeLock() * sizeof(*sql_lock->getLocks()));
 
252
           sql_lock->lock_count * sizeof(*sql_lock->getLocks()));
244
253
    /* Lock on the copied half of the lock data array. */
245
 
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(*this,
246
 
                                                     sql_lock->getLocks() +
247
 
                                                     sql_lock->sizeLock(),
248
 
                                                     sql_lock->sizeLock(),
 
254
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->getLocks() +
 
255
                                                     sql_lock->lock_count,
 
256
                                                     sql_lock->lock_count,
249
257
                                                     this->lock_id)];
250
258
    if (rc > 1)                                 /* a timeout or a deadlock */
251
259
    {
252
 
      if (sql_lock->sizeTable())
253
 
        unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
 
260
      if (sql_lock->table_count)
 
261
        unlock_external(sql_lock->getTable(), sql_lock->table_count);
254
262
      reset_lock_data_and_free(&sql_lock);
255
263
      my_error(rc, MYF(0));
256
264
      break;
257
265
    }
258
266
    else if (rc == 1)                           /* aborted */
259
267
    {
260
 
      some_tables_deleted= true;                // Try again
261
 
      sql_lock->setLock(0);                  // Locks are already freed
 
268
      some_tables_deleted= 1;           // Try again
 
269
      sql_lock->lock_count= 0;                  // Locks are already freed
262
270
      // Fall through: unlock, reset lock data, free and retry
263
271
    }
264
272
    else if (not some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH))
272
280
    else if (not open_tables)
273
281
    {
274
282
      // Only using temporary tables, no need to unlock
275
 
      some_tables_deleted= false;
 
283
      some_tables_deleted= 0;
276
284
      break;
277
285
    }
278
286
    set_proc_info(0);
279
287
 
280
288
    /* going to retry, unlock all tables */
281
 
    if (sql_lock->sizeLock())
282
 
        sql_lock->unlock(sql_lock->sizeLock());
 
289
    if (sql_lock->lock_count)
 
290
        sql_lock->unlock(sql_lock->lock_count);
283
291
 
284
 
    if (sql_lock->sizeTable())
285
 
      unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
 
292
    if (sql_lock->table_count)
 
293
      unlock_external(sql_lock->getTable(), sql_lock->table_count);
286
294
 
287
295
    /*
288
296
      If thr_multi_lock fails it resets lock type for tables, which
361
369
 
362
370
void Session::unlockTables(DrizzleLock *sql_lock)
363
371
{
364
 
  if (sql_lock->sizeLock())
365
 
    sql_lock->unlock(sql_lock->sizeLock());
366
 
  if (sql_lock->sizeTable())
367
 
    unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
 
372
  if (sql_lock->lock_count)
 
373
    sql_lock->unlock(sql_lock->lock_count);
 
374
  if (sql_lock->table_count)
 
375
    unlock_external(sql_lock->getTable(), sql_lock->table_count);
368
376
  delete sql_lock;
369
377
}
370
378
 
394
402
 
395
403
  /* Move all write locks first */
396
404
  THR_LOCK_DATA **lock_local= sql_lock->getLocks();
397
 
  for (i=found=0 ; i < sql_lock->sizeLock(); i++)
 
405
  for (i=found=0 ; i < sql_lock->lock_count ; i++)
398
406
  {
399
407
    if (sql_lock->getLocks()[i]->type >= TL_WRITE_ALLOW_READ)
400
408
    {
406
414
  /* unlock the read locked tables */
407
415
  if (i != found)
408
416
  {
409
 
    thr_multi_unlock(lock_local, i - found);
410
 
    sql_lock->setLock(found);
 
417
    sql_lock->unlock(i - found);
 
418
    sql_lock->lock_count= found;
411
419
  }
412
420
 
413
421
  /* Then do the same for the external locks */
414
422
  /* Move all write locked tables first */
415
423
  Table **table= sql_lock->getTable();
416
 
  for (i=found=0 ; i < sql_lock->sizeTable() ; i++)
 
424
  for (i=found=0 ; i < sql_lock->table_count ; i++)
417
425
  {
418
426
    assert(sql_lock->getTable()[i]->lock_position == i);
419
427
    if ((uint32_t) sql_lock->getTable()[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
427
435
  if (i != found)
428
436
  {
429
437
    unlock_external(table, i - found);
430
 
    sql_lock->resizeTable(found);
 
438
    sql_lock->table_count=found;
431
439
  }
432
440
  /* Fix the lock positions in Table */
433
441
  table= sql_lock->getTable();
434
442
  found= 0;
435
 
  for (i= 0; i < sql_lock->sizeTable(); i++)
 
443
  for (i= 0; i < sql_lock->table_count; i++)
436
444
  {
437
445
    Table *tbl= *table;
438
446
    tbl->lock_position= table - sql_lock->getTable();
479
487
  if ((locked= get_lock_data(&table, 1, false,
480
488
                             &write_lock_used)))
481
489
  {
482
 
    for (uint32_t x= 0; x < locked->sizeLock(); x++)
 
490
    for (uint32_t x= 0; x < locked->lock_count; x++)
483
491
      locked->getLocks()[x]->lock->abort_locks();
484
492
    delete locked;
485
493
  }
507
515
  if ((locked= get_lock_data(&table, 1, false,
508
516
                             &write_lock_used)))
509
517
  {
510
 
    for (uint32_t i= 0; i < locked->sizeLock(); i++)
 
518
    for (uint32_t i= 0; i < locked->lock_count; i++)
511
519
    {
512
520
      if (locked->getLocks()[i]->lock->abort_locks_for_thread(table->in_use->thread_id))
513
521
        result= true;
556
564
                                    bool should_lock, Table **write_lock_used)
557
565
{
558
566
  uint32_t lock_count;
 
567
  DrizzleLock *sql_lock;
559
568
  THR_LOCK_DATA **locks, **locks_buf, **locks_start;
560
569
  Table **to, **table_buf;
561
570
 
576
585
    update the table values. So the second part of the array is copied
577
586
    from the first part immediately before calling thr_multi_lock().
578
587
  */
579
 
  DrizzleLock *sql_lock= new DrizzleLock(lock_count);
 
588
  sql_lock= new DrizzleLock(lock_count, lock_count*2);
580
589
 
581
590
  if (not sql_lock)
582
591
    return NULL;
602
611
      {
603
612
        my_error(ER_OPEN_AS_READONLY, MYF(0), table->getAlias());
604
613
        /* Clear the lock type of the lock data that are stored already. */
605
 
        sql_lock->setLock(locks - sql_lock->getLocks());
 
614
        sql_lock->lock_count= locks - sql_lock->getLocks();
606
615
        reset_lock_data_and_free(&sql_lock);
607
616
        return NULL;
608
617
      }
632
641
    we may allocate too much, but better safe than memory overrun.
633
642
    And in the FLUSH case, the memory is released quickly anyway.
634
643
  */
635
 
  sql_lock->setLock(locks - locks_buf);
 
644
  sql_lock->lock_count= locks - locks_buf;
636
645
 
637
646
  return sql_lock;
638
647
}
645
654
  @param check_in_use           Do we need to check if table already in use by us
646
655
 
647
656
  @note
648
 
    One must have a lock on table::Cache::singleton().mutex()!
 
657
    One must have a lock on LOCK_open!
649
658
 
650
659
  @warning
651
660
    If you are going to update the table, you should use
741
750
  bool result= false;
742
751
 
743
752
#if 0
744
 
  assert(ownership of table::Cache::singleton().mutex());
 
753
  assert(ownership of LOCK_open);
745
754
#endif
746
755
 
747
756
  while (locked_named_table(table_list))
751
760
      result=1;
752
761
      break;
753
762
    }
754
 
    wait_for_condition(table::Cache::singleton().mutex(), COND_refresh);
755
 
    table::Cache::singleton().mutex().lock(); /* Wait for a table to unlock and then lock it */
 
763
    wait_for_condition(LOCK_open, COND_refresh);
 
764
    LOCK_open.lock(); /* Wait for a table to unlock and then lock it */
756
765
  }
757
766
  return result;
758
767
}
762
771
  Lock all tables in list with a name lock.
763
772
 
764
773
  REQUIREMENTS
765
 
  - One must have a lock on table::Cache::singleton().mutex() when calling this
 
774
  - One must have a lock on LOCK_open when calling this
766
775
 
767
776
  @param table_list             Names of tables to lock
768
777
 
808
817
  @param table_list Names of tables to lock.
809
818
 
810
819
  @note
811
 
    This function needs to be protected by table::Cache::singleton().mutex(). If we're
 
820
    This function needs to be protected by LOCK_open. If we're
812
821
    under LOCK TABLES, this function does not work as advertised. Namely,
813
822
    it does not exclude other threads from using this table and does not
814
823
    put an exclusive name lock on this table into the table cache.
847
856
                                (default 0, which will unlock all tables)
848
857
 
849
858
  @note
850
 
    One must have a lock on table::Cache::singleton().mutex() when calling this.
 
859
    One must have a lock on LOCK_open when calling this.
851
860
 
852
861
  @note
853
862
    This function will broadcast refresh signals to inform other threads
922
931
 
923
932
  access to them is protected with a mutex LOCK_global_read_lock
924
933
 
925
 
  (XXX: one should never take table::Cache::singleton().mutex() if LOCK_global_read_lock is
 
934
  (XXX: one should never take LOCK_open if LOCK_global_read_lock is
926
935
  taken, otherwise a deadlock may occur. Other mutexes could be a
927
936
  problem too - grep the code for global_read_lock if you want to use
928
 
  any other mutex here) Also one must not hold table::Cache::singleton().mutex() when calling
 
937
  any other mutex here) Also one must not hold LOCK_open when calling
929
938
  wait_if_global_read_lock(). When the thread with the global read lock
930
 
  tries to close its tables, it needs to take table::Cache::singleton().mutex() in
 
939
  tries to close its tables, it needs to take LOCK_open in
931
940
  close_thread_table().
932
941
 
933
942
  How blocking of threads by global read lock is achieved: that's
1022
1031
{
1023
1032
  uint32_t tmp;
1024
1033
 
1025
 
  if (not isGlobalReadLock()) // If we have no personal stake in the global lock, just return
1026
 
    return;
1027
 
 
1028
1034
  {
1029
1035
    boost_unique_lock_t scopedLock(LOCK_global_read_lock);
1030
1036
    tmp= --global_read_lock;
1052
1058
  bool result= 0, need_exit_cond;
1053
1059
 
1054
1060
  /*
1055
 
    Assert that we do not own table::Cache::singleton().mutex(). If we would own it, other
 
1061
    Assert that we do not own LOCK_open. If we would own it, other
1056
1062
    threads could not close their tables. This would make a pretty
1057
1063
    deadlock.
1058
1064
  */
1059
 
  safe_mutex_assert_not_owner(table::Cache::singleton().mutex().native_handle());
 
1065
  safe_mutex_assert_not_owner(LOCK_open.native_handle());
1060
1066
 
1061
1067
  LOCK_global_read_lock.lock();
1062
1068
  if ((need_exit_cond= must_wait(is_not_commit)))
1165
1171
    Due to a bug in a threading library it could happen that a signal
1166
1172
    did not reach its target. A condition for this was that the same
1167
1173
    condition variable was used with different mutexes in
1168
 
    pthread_cond_wait(). Some time ago we changed table::Cache::singleton().mutex() to
 
1174
    pthread_cond_wait(). Some time ago we changed LOCK_open to
1169
1175
    LOCK_global_read_lock in global read lock handling. So COND_refresh
1170
 
    was used with table::Cache::singleton().mutex() and LOCK_global_read_lock.
 
1176
    was used with LOCK_open and LOCK_global_read_lock.
1171
1177
 
1172
1178
    We did now also change from COND_refresh to COND_global_read_lock
1173
1179
    in global read lock handling. But now it is necessary to signal