YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense alongwiththisprogram;ifnot,writetotheFreeSoftware
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
if (found_errors < MAX_FOUND_ERRORS)
{ if (check_lock(&lock->write,"write",where,1,1,0) |
check_lock(&lock->write_wait,"write_wait",where,0,0,0) |
check_lock(&lock->read,"read",where,0,1,1) |
check_lock(&lock->read_wait,"read_wait",where,0,0,1))
{
DBUG_ASSERT(my_assert_on_error == 0);
found_errors++;
}
if (found_errors < MAX_FOUND_ERRORS)
{
uint count=0, count2= 0;
THR_LOCK_DATA *data; for (data=lock->read.data ; data ; data=data->next)
{
count2++; if (data->type == TL_READ_NO_INSERT)
count++; /* Protect against infinite loop. */
DBUG_ASSERT(count <= lock->read_no_write_count &&
count2 <= MAX_LOCKS);
} if (count != lock->read_no_write_count)
{
found_errors++;
fprintf(stderr, "Warning at '%s': Locks read_no_write_count was %u when it should have been %u\n", where, lock->read_no_write_count,count);
}
if (!lock->write.data)
{ if (!allow_no_locks && !lock->read.data &&
(lock->write_wait.data || lock->read_wait.data))
{
found_errors++;
fprintf(stderr, "Warning at '%s': No locks in use but locks are in wait queue\n",
where);
} if (!lock->write_wait.data)
{ if (!allow_no_locks && lock->read_wait.data)
{
found_errors++;
fprintf(stderr, "Warning at '%s': No write locks and waiting read locks\n",
where);
}
} else
{ if (!allow_no_locks &&
(((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT ||
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) &&
!lock->read_no_write_count) ||
(lock->write_wait.data->type == TL_WRITE_DELAYED &&
!lock->read.data)))
{
found_errors++;
fprintf(stderr, "Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type);
DBUG_PRINT("warning", ("Warning at '%s': Write lock %d waiting while no exclusive read locks",where,(int) lock->write_wait.data->type));
}
}
} else
{ /* We have at least one write lock */ if (lock->write.data->type == TL_WRITE_CONCURRENT_INSERT)
{
count= 0; for (data=lock->write.data->next;
data && count < MAX_LOCKS;
data=data->next)
{ if (data->type != TL_WRITE_CONCURRENT_INSERT &&
data->type != TL_WRITE_ALLOW_WRITE)
{
fprintf(stderr, "Warning at '%s': Found TL_WRITE_CONCURRENT_INSERT lock mixed with other write lock: %d\n",
where, data->type);
DBUG_PRINT("warning", ("Warning at '%s': Found TL_WRITE_CONCURRENT_INSERT lock mixed with other write lock: %d",
where, data->type)); break;
}
}
} if (lock->write_wait.data)
{ if (!allow_no_locks &&
lock->write.data->type == TL_WRITE_ALLOW_WRITE &&
lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE)
{
found_errors++;
fprintf(stderr, "Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n",
where);
DBUG_PRINT("warning", ("Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock",
where));
}
} if (lock->read.data)
{ for (data=lock->read.data ; data ; data=data->next)
{ if (!thr_lock_owner_equal(lock->write.data->owner,
data->owner) &&
((lock->write.data->type > TL_WRITE_DELAYED &&
lock->write.data->type != TL_WRITE_ONLY) ||
((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT ||
lock->write.data->type == TL_WRITE_ALLOW_WRITE) &&
data->type == TL_READ_NO_INSERT)))
{
found_errors++;
fprintf(stderr, "Warning at '%s' for lock: %d: Found lock of type %d that is write and read locked. Read_no_write_count: %d\n",
where, (int) type, lock->write.data->type,
lock->read_no_write_count);
DBUG_PRINT("warning",("At '%s' for lock %d: Found lock of type %d that is write and read locked",
where, (int) type,
lock->write.data->type));
}
}
} if (lock->read_wait.data)
{ if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED &&
lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY)
{
found_errors++;
fprintf(stderr, "Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n",
where,
(int) lock->read_wait.data->type,
(int) lock->write.data->type);
}
}
}
} if (found_errors != old_found_errors)
{
DBUG_PRINT("error",("Found wrong lock"));
}
}
DBUG_VOID_RETURN;
}
mysql_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */
lock->list.data=(void*) lock;
thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list);
mysql_mutex_unlock(&THR_LOCK_lock);
DBUG_VOID_RETURN;
}
/* Set up control struct to allow others to abort locks */
thread_var->current_mutex= &data->lock->mutex;
thread_var->current_cond= cond;
data->cond= cond;
if (data->cond || data->type == TL_UNLOCK)
{ if (data->cond) /* aborted or timed out */
{ if (((*data->prev)=data->next)) /* remove from wait-list */
data->next->prev= data->prev; else
wait->last=data->prev;
data->type= TL_UNLOCK; /* No lock */
check_locks(data->lock, "killed or timed out wait_for_lock", data->type, 1);
wake_up_waiters(data->lock);
} else
{
DBUG_PRINT("thr_lock", ("lock aborted"));
check_locks(data->lock, "aborted wait_for_lock", data->type, 0);
}
} else
{
result= THR_LOCK_SUCCESS; if (data->lock->get_status &&
(*data->lock->get_status)(data->status_param,
data->type == TL_WRITE_CONCURRENT_INSERT))
result= THR_LOCK_ABORTED;
check_locks(data->lock,"got wait_for_lock", data->type, 0);
}
mysql_mutex_unlock(&data->lock->mutex);
/* The following must be done after unlock of lock->mutex */
mysql_mutex_lock(&thread_var->mutex);
thread_var->current_mutex= 0;
thread_var->current_cond= 0;
mysql_mutex_unlock(&thread_var->mutex);
DBUG_PRINT("lock",("write locked 1 by thread:%lu",
(ulong) lock->write.data->owner->thread_id)); if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
(lock->write.data->type <= TL_WRITE_DELAYED &&
(((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) ||
(lock->write.data->type != TL_WRITE_CONCURRENT_INSERT))))
{ /* Already got a write lock */
(*lock->read.last)=data; /* Add to running FIFO */
data->prev=lock->read.last;
lock->read.last= &data->next; if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count++;
check_locks(lock,"read lock with old write lock", lock_type, 0); if ((lock->get_status) && (*lock->get_status)(data->status_param, 0))
result= THR_LOCK_ABORTED;
statistic_increment(locks_immediate,&THR_LOCK_lock); goto end;
} if (lock->write.data->type == TL_WRITE_ONLY)
{ /* We are not allowed to get a READ lock in this case */
data->type=TL_UNLOCK;
result= THR_LOCK_ABORTED; /* Can't wait for this one */ goto end;
}
} elseif (!lock->write_wait.data ||
lock->write_wait.data->type <= TL_WRITE_LOW_PRIORITY ||
lock_type == TL_READ_HIGH_PRIORITY ||
has_old_lock(lock->read.data, data->owner)) /* Has old read lock */
{ /* No important write-locks */
(*lock->read.last)=data; /* Add to running FIFO */
data->prev=lock->read.last;
lock->read.last= &data->next; if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count++;
check_locks(lock,"read lock with no write locks", lock_type, 0); if ((lock->get_status) && (*lock->get_status)(data->status_param, 0))
result= THR_LOCK_ABORTED;
statistic_increment(locks_immediate,&THR_LOCK_lock); goto end;
} /* We'rehereifthereisanactivewritelockornowrite lockbutahighprioritywritewaitinginthewrite_waitqueue. Inthelattercaseweshouldyieldthelocktothewriter.
*/
wait_queue= &lock->read_wait;
} else/* Request for WRITE lock */
{ if (lock_type == TL_WRITE_DELAYED)
{ if (lock->write.data && lock->write.data->type == TL_WRITE_ONLY)
{
data->type=TL_UNLOCK;
result= THR_LOCK_ABORTED; /* Can't wait for this one */ goto end;
} if (lock->write.data || lock->read.data)
{ /* Add delayed write lock to write_wait queue, and return at once */
(*lock->write_wait.last)=data;
data->prev=lock->write_wait.last;
lock->write_wait.last= &data->next;
data->cond=get_cond(); /* Wedon'thavetodoget_statushereaswewilldoitwhenwechange thedelayedlocktoarealwritelock
*/
statistic_increment(locks_immediate,&THR_LOCK_lock); goto end;
}
} elseif (lock_type == TL_WRITE_CONCURRENT_INSERT && ! lock->check_status)
data->type=lock_type= thr_upgraded_concurrent_insert_lock;
if (lock->write.data) /* If there is a write lock */
{ if (lock->write.data->type == TL_WRITE_ONLY)
{ /* purecov: begin tested */ /* Allow lock owner to bypass TL_WRITE_ONLY. */ if (!thr_lock_owner_equal(data->owner, lock->write.data->owner))
{ /* We are not allowed to get a lock in this case */
data->type=TL_UNLOCK;
result= THR_LOCK_ABORTED; /* Can't wait for this one */ goto end;
} /* purecov: end */
}
if (((*data->prev)=data->next)) /* remove from lock-list */
data->next->prev= data->prev; elseif (lock_type <= TL_READ_NO_INSERT)
lock->read.last=data->prev; elseif (lock_type == TL_WRITE_DELAYED && data->cond)
{ /* Thisonlyhappensinextremecircumstanceswhena writedelayedlockthatiswaitingforalock
*/
lock->write_wait.last=data->prev; /* Put it on wait queue */
} else
lock->write.last=data->prev;
if (unlock_flags & THR_UNLOCK_UPDATE_STATUS)
{ /* External lock was not called; Update or restore status */ if (lock_type >= TL_WRITE_CONCURRENT_INSERT)
{ if (lock->update_status)
(*lock->update_status)(data->status_param);
} else
{ if (lock->restore_status)
(*lock->restore_status)(data->status_param);
}
} if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count--;
data->type=TL_UNLOCK; /* Mark unlocked */
wake_up_waiters(lock);
mysql_mutex_unlock(&lock->mutex);
DBUG_VOID_RETURN;
}
/* Sort locks with insertion sort (fast because almost always few locks) */
for (pos=data+1,end=data+count; pos < end ; pos++)
{
tmp= *pos; if (LOCK_CMP(tmp,pos[-1]))
{
prev=pos; do {
prev[0]=prev[-1];
} while (--prev != data && LOCK_CMP(tmp,prev[-1]));
prev[0]=tmp;
}
}
}
if (count > 1)
sort_locks(data,count); elseif (count == 0)
DBUG_RETURN(THR_LOCK_SUCCESS);
/* lock everything */
DEBUG_SYNC_C("thr_multi_lock_before_thr_lock"); for (pos=data,end=data+count; pos < end ; pos++)
{ enum enum_thr_lock_result result= thr_lock(*pos, owner, lock_wait_timeout); if (result != THR_LOCK_SUCCESS)
{ /* Aborted */
thr_multi_unlock(data,(uint) (pos-data), 0); /* Mark all requested locks as TL_UNLOCK (to simplify lock checking) */ for ( ; pos < end ; pos++)
(*pos)->type= TL_UNLOCK;
DBUG_RETURN(result);
} #ifdef MAIN
printf("Thread: %s Got lock:%p type: %d\n",my_thread_name(),
pos[0]->lock, pos[0]->type); fflush(stdout); #endif
}
DEBUG_SYNC_C("thr_multi_lock_after_thr_lock");
/* Callstart_transforalllocks. Ifwelockthesametablemultipletimes,wemustusethesame status_param;Weensurethisbycallingcopy_status()forall copiesofthesametables.
*/ if ((*data)->lock->start_trans)
((*data)->lock->start_trans)((*data)->status_param); for (first_lock=data, pos= data+1 ; pos < end ; pos++)
{ /* Get the current status (row count, checksum, trid etc) */ if ((*pos)->lock->start_trans)
(*(*pos)->lock->start_trans)((*pos)->status_param); /* Ifsametableasprevioustableusepointertopreviousstatus informationtoensurethatallread/writetablessharessame state.
*/ if (pos[0]->lock == pos[-1]->lock && pos[0]->lock->copy_status)
(pos[0]->lock->copy_status)((*pos)->status_param,
(*first_lock)->status_param); else
{ /* Different lock, use this as base for next lock */
first_lock= pos;
}
}
DBUG_RETURN(THR_LOCK_SUCCESS);
}
/* Remove marks on old locks to make them sort before new ones */ for (pos=data, end= pos + old_count; pos < end ; pos++)
(*pos)->priority&= ~THR_LOCK_LATE_PRIV;
/* Mark new locks with LATE_PRIV to make them sort after org ones */ for (pos=data + old_count, end= pos + new_count; pos < end ; pos++)
(*pos)->priority|= THR_LOCK_LATE_PRIV;
sort_locks(data, old_count + new_count);
for (pos=data ; pos < end ; pos++)
{ /* Check if lock was unlocked before */ if (pos[0]->type == TL_UNLOCK || ! pos[0]->lock->fix_status)
{
DBUG_PRINT("info", ("lock skipped. unlocked: %d fix_status: %d",
pos[0]->type == TL_UNLOCK,
pos[0]->lock->fix_status == 0)); continue;
}
/* Ifsametableasprevioustableusepointertopreviousstatus informationtoensurethatallread/writetablessharessame state.
*/ if (first_lock && pos[0]->lock == first_lock[0]->lock)
(pos[0]->lock->fix_status)((*first_lock)->status_param,
(*pos)->status_param); else
{ /* Different lock, use this as base for next lock */
first_lock= pos;
(pos[0]->lock->fix_status)((*first_lock)->status_param, 0);
}
}
DBUG_VOID_RETURN;
}
for (data=lock->read_wait.data; data ; data=data->next)
{
data->type=TL_UNLOCK; /* Mark killed */ /* It's safe to signal the cond first: we're still holding the mutex. */
mysql_cond_signal(data->cond);
data->cond=0; /* Removed from list */
} for (data=lock->write_wait.data; data ; data=data->next)
{
data->type=TL_UNLOCK;
mysql_cond_signal(data->cond);
data->cond=0;
}
lock->read_wait.last= &lock->read_wait.data;
lock->write_wait.last= &lock->write_wait.data;
lock->read_wait.data=lock->write_wait.data=0; if (upgrade_lock && lock->write.data)
lock->write.data->type=TL_WRITE_ONLY;
mysql_mutex_unlock(&lock->mutex);
DBUG_VOID_RETURN;
}
mysql_mutex_lock(&lock->mutex); for (data= lock->read_wait.data; data ; data= data->next)
{ if (data->owner->thread_id == thread_id) /* purecov: tested */
{
DBUG_PRINT("info",("Aborting read-wait lock"));
data->type= TL_UNLOCK; /* Mark killed */ /* It's safe to signal the cond first: we're still holding the mutex. */
found= TRUE;
mysql_cond_signal(data->cond);
data->cond= 0; /* Removed from list */
if (((*data->prev)= data->next))
data->next->prev= data->prev; else
lock->read_wait.last= data->prev;
}
} for (data= lock->write_wait.data; data ; data= data->next)
{ if (data->owner->thread_id == thread_id) /* purecov: tested */
{
DBUG_PRINT("info",("Aborting write-wait lock"));
data->type= TL_UNLOCK;
found= TRUE;
mysql_cond_signal(data->cond);
data->cond= 0;
mysql_mutex_lock(&lock->mutex); if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY)
{
mysql_mutex_unlock(&lock->mutex);
DBUG_RETURN(data->type == TL_UNLOCK); /* Test if Aborted */
}
check_locks(lock,"before upgrading lock", data->type, 0); /* TODO: Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */
data->type= new_lock_type; /* Upgrade lock */
/* Check if someone has given us the lock */ if (!data->cond)
{ if (!lock->read.data) /* No read locks */
{ /* We have the lock */ /* For this function, get_status is not allowed to fail */ if (data->lock->get_status)
(*data->lock->get_status)(data->status_param, 0);
mysql_mutex_unlock(&lock->mutex); if (lock->start_trans)
(*lock->start_trans)(data->status_param);
DBUG_RETURN(0);
}
if (((*data->prev)=data->next)) /* remove from lock-list */
data->next->prev= data->prev; else
lock->write.last=data->prev;
if ((data->next=lock->write_wait.data)) /* Put first in lock_list */
data->next->prev= &data->next; else
lock->write_wait.last= &data->next;
data->prev= &lock->write_wait.data;
lock->write_wait.data=data;
check_locks(lock,"upgrading lock", new_lock_type, 0);
} else
{
check_locks(lock,"waiting for lock", new_lock_type, 0);
}
res= wait_for_lock(&lock->write_wait, data, 1, lock_wait_timeout); if (res == THR_LOCK_SUCCESS && lock->start_trans)
DBUG_RETURN((*lock->start_trans)(data->status_param));
DBUG_RETURN(0);
}
/* downgrade a WRITE lock to a WRITE_DELAY lock if there is pending locks */
mysql_mutex_lock(&lock->mutex); if (!lock->read_wait.data) /* No waiting read locks */
{
mysql_mutex_unlock(&lock->mutex);
DBUG_RETURN(0);
}
write_lock_type= data->type;
data->type=TL_WRITE_DELAYED; if (lock->update_status)
(*lock->update_status)(data->status_param); if (((*data->prev)=data->next)) /* remove from lock-list */
data->next->prev= data->prev; else
lock->write.last=data->prev;
if ((data->next=lock->write_wait.data)) /* Put first in lock_list */
data->next->prev= &data->next; else
lock->write_wait.last= &data->next;
data->prev= &lock->write_wait.data;
data->cond=get_cond(); /* This was zero */
lock->write_wait.data=data;
free_all_read_locks(lock,0);
if (list->data)
{
printf("%-10s: ",name);
prev= &list->data; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
{
printf("%p (%lu:%d); ", data, (ulong) data->owner->thread_id,
(int) data->type); if (data->prev != prev)
printf("\nWarning: prev didn't point at previous lock\n");
prev= &data->next;
}
puts(""); if (prev != list->last)
printf("Warning: last didn't point at last lock\n");
}
}
void thr_print_locks(void)
{
LIST *list;
uint count=0;
mysql_mutex_lock(&THR_LOCK_lock);
puts("Current active THR (table level locks):"); for (list= thr_lock_thread_list; list && count++ < MAX_THREADS;
list= list_rest(list))
{
THR_LOCK *lock=(THR_LOCK*) list->data;
mysql_mutex_lock(&lock->mutex); if ((lock->write.data || lock->read.data ||
lock->write_wait.data || lock->read_wait.data))
{
printf("lock: %p:", lock); if ((lock->write_wait.data || lock->read_wait.data) &&
(! lock->read.data && ! lock->write.data))
printf(" WARNING: "); if (lock->write.data)
printf(" write"); if (lock->write_wait.data)
printf(" write_wait"); if (lock->read.data)
printf(" read"); if (lock->read_wait.data)
printf(" read_wait");
puts("");
thr_print_lock("write",&lock->write);
thr_print_lock("write_wait",&lock->write_wait);
thr_print_lock("read",&lock->read);
thr_print_lock("read_wait",&lock->read_wait);
puts("");
}
mysql_mutex_unlock(&lock->mutex);
}
fflush(stdout);
mysql_mutex_unlock(&THR_LOCK_lock);
}
pthread_attr_destroy(&thr_attr); if ((error= mysql_mutex_lock(&LOCK_thread_count)))
fprintf(stderr, "Got error: %d from mysql_mutex_lock\n", error); while (thread_count)
{ if ((error= mysql_cond_wait(&COND_thread_count, &LOCK_thread_count)))
fprintf(stderr, "Got error: %d from mysql_cond_wait\n", error);
} if ((error= mysql_mutex_unlock(&LOCK_thread_count)))
fprintf(stderr, "Got error: %d from mysql_mutex_unlock\n", error); for (i=0 ; i < array_elements(locks) ; i++)
thr_lock_delete(locks+i); #ifdef EXTRA_DEBUG if (found_errors)
printf("Got %d warnings\n",found_errors); else #endif
printf("Test succeeded\n");
mysql_cond_destroy(&COND_thread_count);
mysql_mutex_destroy(&LOCK_thread_count);
my_end(MY_CHECK_ERROR); return0;
}
#endif/* MAIN */
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.77Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.