~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/lock.cc

  • Committer: lbieber at stabletransit
  • Date: 2010-10-19 14:03:27 UTC
  • mfrom: (1861.1.2 build)
  • Revision ID: lbieber@drizzle-build-n02.wc1.dfw1.stabletransit.com-20101019140327-2jvt5j2wi4pzhm1z
Merge Brian - Small collection of cleanups/refactor'ing around locks
Merge Monty - fix a few things in the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
      This is followed by a call to thr_multi_lock() for all tables.
35
35
 
36
36
  - When statement is done, we call mysql_unlock_tables().
37
 
    This will call thr_multi_unlock() followed by
 
37
    This will call DrizzleLock::unlock() followed by
38
38
    table_handler->external_lock(session, F_UNLCK) for each table.
39
39
 
40
40
  - Note that mysql_unlock_tables() may be called several times as
164
164
static void reset_lock_data_and_free(DrizzleLock **mysql_lock)
165
165
{
166
166
  DrizzleLock *sql_lock= *mysql_lock;
167
 
  THR_LOCK_DATA **ldata, **ldata_end;
168
 
 
169
 
  /* Clear the lock type of all lock data to avoid reusage. */
170
 
  for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
171
 
       ldata < ldata_end;
172
 
       ldata++)
173
 
  {
174
 
    /* Reset lock type. */
175
 
    (*ldata)->type= TL_UNLOCK;
176
 
  }
177
 
  free((unsigned char*) sql_lock);
 
167
  sql_lock->reset();
 
168
  delete sql_lock;
178
169
  *mysql_lock= 0;
179
170
}
180
171
 
 
172
void DrizzleLock::reset(void)
 
173
{
 
174
  for (std::vector<THR_LOCK_DATA *>::iterator iter= locks.begin(); iter != locks.end(); iter++)
 
175
  {
 
176
    (*iter)->type= TL_UNLOCK;
 
177
  }
 
178
}
 
179
 
181
180
 
182
181
DrizzleLock *mysql_lock_tables(Session *session, Table **tables, uint32_t count,
183
182
                                uint32_t flags, bool *need_reopen)
247
246
     * of the type of lock that Drizzle intends to take on a 
248
247
     * specific table.
249
248
     */
250
 
    if (sql_lock->table_count && lock_external(session, sql_lock->table,
 
249
    if (sql_lock->table_count && lock_external(session, sql_lock->getTable(),
251
250
                                               sql_lock->table_count))
252
251
    {
253
252
      /* Clear the lock type of all lock data to avoid reusage. */
256
255
    }
257
256
    session->set_proc_info("Table lock");
258
257
    /* Copy the lock data array. thr_multi_lock() reorders its contens. */
259
 
    memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
260
 
           sql_lock->lock_count * sizeof(*sql_lock->locks));
 
258
    memcpy(sql_lock->getLocks() + sql_lock->lock_count,
 
259
           sql_lock->getLocks(),
 
260
           sql_lock->lock_count * sizeof(*sql_lock->getLocks()));
261
261
    /* Lock on the copied half of the lock data array. */
262
 
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
 
262
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->getLocks() +
263
263
                                                     sql_lock->lock_count,
264
264
                                                     sql_lock->lock_count,
265
265
                                                     session->lock_id)];
266
266
    if (rc > 1)                                 /* a timeout or a deadlock */
267
267
    {
268
268
      if (sql_lock->table_count)
269
 
        unlock_external(session, sql_lock->table, sql_lock->table_count);
 
269
        unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
270
270
      reset_lock_data_and_free(&sql_lock);
271
271
      my_error(rc, MYF(0));
272
272
      break;
295
295
 
296
296
    /* going to retry, unlock all tables */
297
297
    if (sql_lock->lock_count)
298
 
        thr_multi_unlock(sql_lock->locks, sql_lock->lock_count);
 
298
        sql_lock->unlock(sql_lock->lock_count);
299
299
 
300
300
    if (sql_lock->table_count)
301
 
      unlock_external(session, sql_lock->table, sql_lock->table_count);
 
301
      unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
302
302
 
303
303
    /*
304
304
      If thr_multi_lock fails it resets lock type for tables, which
340
340
 
341
341
static int lock_external(Session *session, Table **tables, uint32_t count)
342
342
{
343
 
  register uint32_t i;
344
343
  int lock_type,error;
345
 
  for (i=1 ; i <= count ; i++, tables++)
 
344
  for (uint32_t i= 1 ; i <= count ; i++, tables++)
346
345
  {
347
346
    assert((*tables)->reginfo.lock_type >= TL_READ);
348
347
    lock_type=F_WRLCK;                          /* Lock exclusive */
375
374
void mysql_unlock_tables(Session *session, DrizzleLock *sql_lock)
376
375
{
377
376
  if (sql_lock->lock_count)
378
 
    thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
 
377
    sql_lock->unlock(sql_lock->lock_count);
379
378
  if (sql_lock->table_count)
380
 
    unlock_external(session, sql_lock->table, sql_lock->table_count);
381
 
  free((unsigned char*) sql_lock);
382
 
  return;
 
379
    unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
 
380
  delete sql_lock;
383
381
}
384
382
 
385
383
/**
407
405
  uint32_t i,found;
408
406
 
409
407
  /* Move all write locks first */
410
 
  THR_LOCK_DATA **lock=sql_lock->locks;
 
408
  THR_LOCK_DATA **lock=sql_lock->getLocks();
411
409
  for (i=found=0 ; i < sql_lock->lock_count ; i++)
412
410
  {
413
 
    if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_READ)
 
411
    if (sql_lock->getLocks()[i]->type >= TL_WRITE_ALLOW_READ)
414
412
    {
415
 
      std::swap(*lock, sql_lock->locks[i]);
 
413
      std::swap(*lock, sql_lock->getLocks()[i]);
416
414
      lock++;
417
415
      found++;
418
416
    }
420
418
  /* unlock the read locked tables */
421
419
  if (i != found)
422
420
  {
423
 
    thr_multi_unlock(lock,i-found);
 
421
    sql_lock->unlock(i - found);
424
422
    sql_lock->lock_count= found;
425
423
  }
426
424
 
427
425
  /* Then do the same for the external locks */
428
426
  /* Move all write locked tables first */
429
 
  Table **table=sql_lock->table;
 
427
  Table **table= sql_lock->getTable();
430
428
  for (i=found=0 ; i < sql_lock->table_count ; i++)
431
429
  {
432
 
    assert(sql_lock->table[i]->lock_position == i);
433
 
    if ((uint32_t) sql_lock->table[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
 
430
    assert(sql_lock->getTable()[i]->lock_position == i);
 
431
    if ((uint32_t) sql_lock->getTable()[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
434
432
    {
435
 
      std::swap(*table, sql_lock->table[i]);
 
433
      std::swap(*table, sql_lock->getTable()[i]);
436
434
      table++;
437
435
      found++;
438
436
    }
444
442
    sql_lock->table_count=found;
445
443
  }
446
444
  /* Fix the lock positions in Table */
447
 
  table= sql_lock->table;
 
445
  table= sql_lock->getTable();
448
446
  found= 0;
449
447
  for (i= 0; i < sql_lock->table_count; i++)
450
448
  {
451
449
    Table *tbl= *table;
452
 
    tbl->lock_position= table - sql_lock->table;
 
450
    tbl->lock_position= table - sql_lock->getTable();
453
451
    tbl->lock_data_start= found;
454
452
    found+= tbl->lock_count;
455
453
    table++;
495
493
                             &write_lock_used)))
496
494
  {
497
495
    for (uint32_t x= 0; x < locked->lock_count; x++)
498
 
      locked->locks[x]->lock->abort_locks();
499
 
    free((unsigned char*) locked);
 
496
      locked->getLocks()[x]->lock->abort_locks();
 
497
    delete locked;
500
498
  }
501
499
}
502
500
 
524
522
  {
525
523
    for (uint32_t i= 0; i < locked->lock_count; i++)
526
524
    {
527
 
      if (locked->locks[i]->lock->abort_locks_for_thread(table->in_use->thread_id))
 
525
      if (locked->getLocks()[i]->lock->abort_locks_for_thread(table->in_use->thread_id))
528
526
        result= true;
529
527
    }
530
 
    free((unsigned char*) locked);
 
528
    delete locked;
531
529
  }
532
530
  return result;
533
531
}
534
532
 
535
533
/** Unlock a set of external. */
536
534
 
537
 
static int unlock_external(Session *session, Table **table,uint32_t count)
 
535
static int unlock_external(Session *session, Table **table, uint32_t count)
538
536
{
539
537
  int error,error_code;
540
538
 
570
568
static DrizzleLock *get_lock_data(Session *session, Table **table_ptr, uint32_t count,
571
569
                                 bool should_lock, Table **write_lock_used)
572
570
{
573
 
  uint32_t tables,lock_count;
 
571
  uint32_t lock_count;
574
572
  DrizzleLock *sql_lock;
575
573
  THR_LOCK_DATA **locks, **locks_buf, **locks_start;
576
574
  Table **to, **table_buf;
577
575
 
578
576
  *write_lock_used=0;
579
 
  for (uint32_t i= tables= lock_count= 0 ; i < count ; i++)
 
577
  for (uint32_t i= lock_count= 0 ; i < count ; i++)
580
578
  {
581
579
    Table *t= table_ptr[i];
582
580
 
583
581
    if (! (t->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK)))
584
582
    {
585
 
      tables++;
586
583
      lock_count++;
587
584
    }
588
585
  }
593
590
    update the table values. So the second part of the array is copied
594
591
    from the first part immediately before calling thr_multi_lock().
595
592
  */
596
 
  if (!(sql_lock= (DrizzleLock*)
597
 
        malloc(sizeof(*sql_lock) +
598
 
               sizeof(THR_LOCK_DATA*) * tables * 2 +
599
 
               sizeof(table_ptr) * lock_count)))
600
 
  {
 
593
  sql_lock= new DrizzleLock(lock_count, lock_count*2);
 
594
 
 
595
  if (not sql_lock)
601
596
    return NULL;
602
 
  }
603
 
  locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
604
 
  to= table_buf= sql_lock->table= (Table**) (locks + tables * 2);
605
 
  sql_lock->table_count= lock_count;
 
597
 
 
598
  locks= locks_buf= sql_lock->getLocks();
 
599
  to= table_buf= sql_lock->getTable();
606
600
 
607
601
  for (uint32_t i= 0; i < count ; i++)
608
602
  {
622
616
      {
623
617
        my_error(ER_OPEN_AS_READONLY, MYF(0), table->getAlias());
624
618
        /* Clear the lock type of the lock data that are stored already. */
625
 
        sql_lock->lock_count= locks - sql_lock->locks;
 
619
        sql_lock->lock_count= locks - sql_lock->getLocks();
626
620
        reset_lock_data_and_free(&sql_lock);
627
621
        return NULL;
628
622
      }