~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/thr_lock.cc

  • Committer: Brian Aker
  • Date: 2009-05-12 03:22:59 UTC
  • mfrom: (1008.1.1 merge)
  • Revision ID: brian@gaz-20090512032259-koqm71phusfj5ntd
Merging Brian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
TL_WRITE_ALLOW_READ     # Write lock, but allow reading
33
33
TL_WRITE_CONCURRENT_INSERT
34
34
                        # Insert that can be mixed when selects
35
 
TL_WRITE_DELAYED        # Used by delayed insert
36
 
                        # Allows lower locks to take over
37
35
TL_WRITE_LOW_PRIORITY   # Low priority write
38
36
TL_WRITE                # High priority write
39
37
TL_WRITE_ONLY           # High priority write
65
63
        for concurrent reads.
66
64
 
67
65
The lock algorithm allows one to have one TL_WRITE_ALLOW_READ,
68
 
TL_WRITE_CONCURRENT_INSERT or one TL_WRITE_DELAYED lock at the same time as
69
 
multiple read locks.
 
66
TL_WRITE_CONCURRENT_INSERT lock at the same time as multiple read locks.
70
67
 
71
68
*/
72
69
 
313
310
      */
314
311
 
315
312
      if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
316
 
          (lock->write.data->type <= TL_WRITE_DELAYED &&
 
313
          (lock->write.data->type <= TL_WRITE_CONCURRENT_INSERT &&
317
314
           (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) ||
318
315
            (lock->write.data->type != TL_WRITE_CONCURRENT_INSERT &&
319
316
             lock->write.data->type != TL_WRITE_ALLOW_READ))))
360
357
  }
361
358
  else                                          /* Request for WRITE lock */
362
359
  {
363
 
    if (lock_type == TL_WRITE_DELAYED)
364
 
    {
365
 
      if (lock->write.data && lock->write.data->type == TL_WRITE_ONLY)
366
 
      {
367
 
        data->type=TL_UNLOCK;
368
 
        result= THR_LOCK_ABORTED;               /* Can't wait for this one */
369
 
        goto end;
370
 
      }
371
 
      /*
372
 
        if there is a TL_WRITE_ALLOW_READ lock, we have to wait for a lock
373
 
        (TL_WRITE_ALLOW_READ is used for ALTER TABLE in MySQL)
374
 
      */
375
 
      if ((!lock->write.data ||
376
 
           lock->write.data->type != TL_WRITE_ALLOW_READ) &&
377
 
          !have_specific_lock(lock->write_wait.data,TL_WRITE_ALLOW_READ) &&
378
 
          (lock->write.data || lock->read.data))
379
 
      {
380
 
        /* Add delayed write lock to write_wait queue, and return at once */
381
 
        (*lock->write_wait.last)=data;
382
 
        data->prev=lock->write_wait.last;
383
 
        lock->write_wait.last= &data->next;
384
 
        data->cond=get_cond();
385
 
        /*
386
 
          We don't have to do get_status here as we will do it when we change
387
 
          the delayed lock to a real write lock
388
 
        */
389
 
        statistic_increment(locks_immediate,&THR_LOCK_lock);
390
 
        goto end;
391
 
      }
392
 
    }
393
 
    else if (lock_type == TL_WRITE_CONCURRENT_INSERT && ! lock->check_status)
 
360
    if (lock_type == TL_WRITE_CONCURRENT_INSERT && ! lock->check_status)
394
361
      data->type=lock_type= thr_upgraded_concurrent_insert_lock;
395
362
 
396
363
    if (lock->write.data)                       /* If there is a write lock */
447
414
        }
448
415
 
449
416
        if (!lock->read.data ||
450
 
            (lock_type <= TL_WRITE_DELAYED &&
 
417
            (lock_type <= TL_WRITE_CONCURRENT_INSERT &&
451
418
             ((lock_type != TL_WRITE_CONCURRENT_INSERT &&
452
419
               lock_type != TL_WRITE_ALLOW_WRITE) ||
453
420
              !lock->read_no_write_count)))
539
506
    data->next->prev= data->prev;
540
507
  else if (lock_type <= TL_READ_NO_INSERT)
541
508
    lock->read.last=data->prev;
542
 
  else if (lock_type == TL_WRITE_DELAYED && data->cond)
543
 
  {
544
 
    /*
545
 
      This only happens in extreme circumstances when a
546
 
      write delayed lock that is waiting for a lock
547
 
    */
548
 
    lock->write_wait.last=data->prev;           /* Put it on wait queue */
549
 
  }
550
509
  else
551
510
    lock->write.last=data->prev;
552
511
  if (lock_type >= TL_WRITE_CONCURRENT_INSERT)
636
595
                             data->type == TL_WRITE_ALLOW_WRITE));
637
596
    }
638
597
    else if (data &&
639
 
             (lock_type=data->type) <= TL_WRITE_DELAYED &&
 
598
             (lock_type=data->type) <= TL_WRITE_CONCURRENT_INSERT &&
640
599
             ((lock_type != TL_WRITE_CONCURRENT_INSERT &&
641
600
               lock_type != TL_WRITE_ALLOW_WRITE) ||
642
601
              !lock->read_no_write_count))
871
830
  pthread_mutex_unlock(&lock->mutex);
872
831
  return(found);
873
832
}
874
 
 
875
 
 
876
 
/*
877
 
  Downgrade a WRITE_* to a lower WRITE level
878
 
  SYNOPSIS
879
 
    thr_downgrade_write_lock()
880
 
    in_data                   Lock data of thread downgrading its lock
881
 
    new_lock_type             New write lock type
882
 
  RETURN VALUE
883
 
    NONE
884
 
  DESCRIPTION
885
 
    This can be used to downgrade a lock already owned. When the downgrade
886
 
    occurs also other waiters, both readers and writers can be allowed to
887
 
    start.
888
 
    The previous lock is often TL_WRITE_ONLY but can also be
889
 
    TL_WRITE and TL_WRITE_ALLOW_READ. The normal downgrade variants are
890
 
    TL_WRITE_ONLY => TL_WRITE_ALLOW_READ After a short exclusive lock
891
 
    TL_WRITE_ALLOW_READ => TL_WRITE_ALLOW_WRITE After discovering that the
892
 
    operation didn't need such a high lock.
893
 
    TL_WRITE_ONLY => TL_WRITE after a short exclusive lock while holding a
894
 
    write table lock
895
 
    TL_WRITE_ONLY => TL_WRITE_ALLOW_WRITE After a short exclusive lock after
896
 
    already earlier having dongraded lock to TL_WRITE_ALLOW_WRITE
897
 
    The implementation is conservative and rather don't start rather than
898
 
    go on unknown paths to start, the common cases are handled.
899
 
 
900
 
    NOTE:
901
 
    In its current implementation it is only allowed to downgrade from
902
 
    TL_WRITE_ONLY. In this case there are no waiters. Thus no wake up
903
 
    logic is required.
904
 
*/
905
 
 
906
 
void thr_downgrade_write_lock(THR_LOCK_DATA *in_data,
907
 
                              enum thr_lock_type new_lock_type)
908
 
{
909
 
  THR_LOCK *lock=in_data->lock;
910
 
 
911
 
  pthread_mutex_lock(&lock->mutex);
912
 
  in_data->type= new_lock_type;
913
 
 
914
 
  pthread_mutex_unlock(&lock->mutex);
915
 
  return;
916
 
}
917
 
 
918
 
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
919
 
 
920
 
bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
921
 
{
922
 
  THR_LOCK *lock=data->lock;
923
 
 
924
 
  pthread_mutex_lock(&lock->mutex);
925
 
  if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY)
926
 
  {
927
 
    pthread_mutex_unlock(&lock->mutex);
928
 
    return(data->type == TL_UNLOCK);    /* Test if Aborted */
929
 
  }
930
 
  /* TODO:  Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */
931
 
  data->type=TL_WRITE;                          /* Upgrade lock */
932
 
 
933
 
  /* Check if someone has given us the lock */
934
 
  if (!data->cond)
935
 
  {
936
 
    if (!lock->read.data)                       /* No read locks */
937
 
    {                                           /* We have the lock */
938
 
      if (data->lock->get_status)
939
 
        (*data->lock->get_status)(data->status_param, 0);
940
 
      pthread_mutex_unlock(&lock->mutex);
941
 
      return(0);
942
 
    }
943
 
 
944
 
    if (((*data->prev)=data->next))             /* remove from lock-list */
945
 
      data->next->prev= data->prev;
946
 
    else
947
 
      lock->write.last=data->prev;
948
 
 
949
 
    if ((data->next=lock->write_wait.data))     /* Put first in lock_list */
950
 
      data->next->prev= &data->next;
951
 
    else
952
 
      lock->write_wait.last= &data->next;
953
 
    data->prev= &lock->write_wait.data;
954
 
    lock->write_wait.data=data;
955
 
  }
956
 
 
957
 
  return(wait_for_lock(&lock->write_wait,data,1));
958
 
}
959
 
 
960
 
 
961
 
/* downgrade a WRITE lock to a WRITE_DELAY lock if there is pending locks */
962
 
 
963
 
bool thr_reschedule_write_lock(THR_LOCK_DATA *data)
964
 
{
965
 
  THR_LOCK *lock=data->lock;
966
 
 
967
 
  pthread_mutex_lock(&lock->mutex);
968
 
  if (!lock->read_wait.data)                    /* No waiting read locks */
969
 
  {
970
 
    pthread_mutex_unlock(&lock->mutex);
971
 
    return(0);
972
 
  }
973
 
 
974
 
  data->type=TL_WRITE_DELAYED;
975
 
  if (lock->update_status)
976
 
    (*lock->update_status)(data->status_param);
977
 
  if (((*data->prev)=data->next))               /* remove from lock-list */
978
 
    data->next->prev= data->prev;
979
 
  else
980
 
    lock->write.last=data->prev;
981
 
 
982
 
  if ((data->next=lock->write_wait.data))       /* Put first in lock_list */
983
 
    data->next->prev= &data->next;
984
 
  else
985
 
    lock->write_wait.last= &data->next;
986
 
  data->prev= &lock->write_wait.data;
987
 
  data->cond=get_cond();                        /* This was zero */
988
 
  lock->write_wait.data=data;
989
 
  free_all_read_locks(lock,0);
990
 
 
991
 
  pthread_mutex_unlock(&lock->mutex);
992
 
  return(thr_upgrade_write_delay_lock(data));
993
 
}