Exemple #1
0
/***********************************************************//**
Moves the query threads in the sig reply wait list of trx to the SUSPENDED
state. */
static
void
trx_sig_reply_wait_to_suspended(
/*============================*/
	trx_t*	trx)	/*!< in: transaction */
{
	trx_sig_t*	sig;
	que_thr_t*	thr;

	ut_ad(mutex_own(&kernel_mutex));

	sig = UT_LIST_GET_FIRST(trx->reply_signals);

	while (sig != NULL) {
		thr = sig->receiver;

		ut_ad(thr->state == QUE_THR_SIG_REPLY_WAIT);

		thr->state = QUE_THR_SUSPENDED;

		sig->receiver = NULL;

		UT_LIST_REMOVE(reply_signals, trx->reply_signals, sig);

		sig = UT_LIST_GET_FIRST(trx->reply_signals);
	}
}
Exemple #2
0
/***********************************************************************
Initializes the old blocks pointer in the LRU list. This function should be
called when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */
static
void
buf_LRU_old_init(void)
/*==================*/
{
	buf_block_t*	block;

	ut_ad(mutex_own(&(buf_pool->mutex)));
	ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);

	/* We first initialize all blocks in the LRU list as old and then use
	the adjust function to move the LRU_old pointer to the right
	position */

	block = UT_LIST_GET_FIRST(buf_pool->LRU);

	while (block != NULL) {
		ut_a(block->state == BUF_BLOCK_FILE_PAGE);
		ut_a(block->in_LRU_list);
		block->old = TRUE;
		block = UT_LIST_GET_NEXT(LRU, block);
	}

	buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU);
	buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU);

	buf_LRU_old_adjust_len();
}
void OSEventThread::firePending()
{
    TRACE("~~~~ +firePending ~~~~\n");
    event_req_t * ev;
    while (ev = UT_LIST_GET_FIRST(mPendingList)) {
        UT_LIST_REMOVE(activeNode,mPendingList,ev);
        try
        {
			ev->func(ev->fd, OSEventContext::EV_RE, ev->param); 
            ev->status = 0;
        }
        catch (...) {
            ERR("Falut req = %p\n",ev);
            ASSERT_C(0);
        }
    }

    event_timer_t * tev;
    while (tev = UT_LIST_GET_FIRST(mTimeoutList)) {
        UT_LIST_REMOVE(activeNode,mTimeoutList,tev);
        try
        {
            tev->func(tev->timeout, tev->param); 
            tev->status = 0;
        }
        catch (...) {
            ERR("Falut timer = %p\n",tev);
            ASSERT_C(0);
        }
    }

    TRACE("~~~~ -firePending ~~~~\n");
}
Exemple #4
0
/******************************************************************//**
Frees the memory allocated dynamically AFTER parsing phase for variables
etc. in the symbol table. Does not free the mem heap where the table was
originally created. Frees also SQL explicit cursor definitions. */
UNIV_INTERN
void
sym_tab_free_private(
/*=================*/
	sym_tab_t*	sym_tab)	/*!< in, own: symbol table */
{
	sym_node_t*	sym;
	func_node_t*	func;

	sym = UT_LIST_GET_FIRST(sym_tab->sym_list);

	while (sym) {
		eval_node_free_val_buf(sym);

		if (sym->prefetch_buf) {
			sel_col_prefetch_buf_free(sym->prefetch_buf);
		}

		if (sym->cursor_def) {
			que_graph_free_recursive(sym->cursor_def);
		}

		sym = UT_LIST_GET_NEXT(sym_list, sym);
	}

	func = UT_LIST_GET_FIRST(sym_tab->func_node_list);

	while (func) {
		eval_node_free_val_buf(func);

		func = UT_LIST_GET_NEXT(func_node_list, func);
	}
}
Exemple #5
0
/*********************************************************//**
Frees created events and OS 'slow' mutexes. */
UNIV_INTERN
void
os_sync_free(void)
/*==============*/
{
	os_event_t	event;
	os_mutex_t	mutex;

	os_sync_free_called = TRUE;
	event = UT_LIST_GET_FIRST(os_event_list);

	while (event) {

		os_event_free(event);

		event = UT_LIST_GET_FIRST(os_event_list);
	}

	mutex = UT_LIST_GET_FIRST(os_mutex_list);

	while (mutex) {
		if (mutex == os_sync_mutex) {
			/* Set the flag to FALSE so that we do not try to
			reserve os_sync_mutex any more in remaining freeing
			operations in shutdown */
			os_sync_mutex_inited = FALSE;
		}

		os_mutex_free(mutex);

		mutex = UT_LIST_GET_FIRST(os_mutex_list);
	}
	os_sync_free_called = FALSE;
}
Exemple #6
0
/***************************************************************//**
Prints debug info of currently locked rw-locks. */
UNIV_INTERN
void
rw_lock_list_print_info(
/*====================*/
	FILE*	file)		/*!< in: file where to print */
{
	rw_lock_t*	lock;
	ulint		count		= 0;
	rw_lock_debug_t* info;

	mutex_enter(&rw_lock_list_mutex);

	fputs("-------------\n"
	      "RW-LATCH INFO\n"
	      "-------------\n", file);

	lock = UT_LIST_GET_FIRST(rw_lock_list);

	while (lock != NULL) {

		count++;

#ifndef INNODB_RW_LOCKS_USE_ATOMICS
		mutex_enter(&(lock->mutex));
#endif
		if (lock->lock_word != X_LOCK_DECR) {

			fprintf(file, "RW-LOCK: %p ", (void*) lock);

			if (rw_lock_get_waiters(lock)) {
				fputs(" Waiters for the lock exist\n", file);
			} else {
				putc('\n', file);
			}

			rw_lock_debug_mutex_enter();
			info = UT_LIST_GET_FIRST(lock->debug_list);
			while (info != NULL) {
				rw_lock_debug_print(file, info);
				info = UT_LIST_GET_NEXT(list, info);
			}
			rw_lock_debug_mutex_exit();
		}
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
		mutex_exit(&(lock->mutex));
#endif

		lock = UT_LIST_GET_NEXT(list, lock);
	}

	fprintf(file, "Total number of rw-locks %ld\n", count);
	mutex_exit(&rw_lock_list_mutex);
}
Exemple #7
0
void
rw_lock_list_print_info(void)
/*=========================*/
{
#ifndef UNIV_SYNC_DEBUG
#else
    rw_lock_t*	lock;
    ulint		count		= 0;
    rw_lock_debug_t* info;

    mutex_enter(&rw_lock_list_mutex);

    printf("-------------\n");
    printf("RW-LATCH INFO\n");
    printf("-------------\n");

    lock = UT_LIST_GET_FIRST(rw_lock_list);

    while (lock != NULL) {

        count++;

        mutex_enter(&(lock->mutex));

        if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
                || (rw_lock_get_reader_count(lock) != 0)
                || (rw_lock_get_waiters(lock) != 0)) {

            printf("RW-LOCK: %lx ", (ulint)lock);

            if (rw_lock_get_waiters(lock)) {
                printf(" Waiters for the lock exist\n");
            } else {
                printf("\n");
            }

            info = UT_LIST_GET_FIRST(lock->debug_list);
            while (info != NULL) {
                rw_lock_debug_print(info);
                info = UT_LIST_GET_NEXT(list, info);
            }
        }

        mutex_exit(&(lock->mutex));
        lock = UT_LIST_GET_NEXT(list, lock);
    }

    printf("Total number of rw-locks %ld\n", count);
    mutex_exit(&rw_lock_list_mutex);
#endif
}
Exemple #8
0
void
rw_lock_list_print_info(
    /*====================*/
    FILE*	file)		/* in: file where to print */
{
    rw_lock_t*	lock;
    ulint		count		= 0;
    rw_lock_debug_t* info;

    mutex_enter(&rw_lock_list_mutex);

    fputs("-------------\n"
          "RW-LATCH INFO\n"
          "-------------\n", file);

    lock = UT_LIST_GET_FIRST(rw_lock_list);

    while (lock != NULL) {

        count++;

        mutex_enter(&(lock->mutex));

        if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
                || (rw_lock_get_reader_count(lock) != 0)
                || (rw_lock_get_waiters(lock) != 0)) {

            fprintf(file, "RW-LOCK: %p ", (void*) lock);

            if (rw_lock_get_waiters(lock)) {
                fputs(" Waiters for the lock exist\n", file);
            } else {
                putc('\n', file);
            }

            info = UT_LIST_GET_FIRST(lock->debug_list);
            while (info != NULL) {
                rw_lock_debug_print(info);
                info = UT_LIST_GET_NEXT(list, info);
            }
        }

        mutex_exit(&(lock->mutex));
        lock = UT_LIST_GET_NEXT(list, lock);
    }

    fprintf(file, "Total number of rw-locks %ld\n", count);
    mutex_exit(&rw_lock_list_mutex);
}
Exemple #9
0
/******************************************************************//**
Assigns a rollback segment to a transaction in a round-robin fashion.
Skips the SYSTEM rollback segment if another is available.
@return	assigned rollback segment id */
UNIV_INLINE
ulint
trx_assign_rseg(void)
/*=================*/
{
	trx_rseg_t*	rseg	= trx_sys->latest_rseg;

	ut_ad(mutex_own(&kernel_mutex));
loop:
	/* Get next rseg in a round-robin fashion */

	rseg = UT_LIST_GET_NEXT(rseg_list, rseg);

	if (rseg == NULL) {
		rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
	}

	/* If it is the SYSTEM rollback segment, and there exist others, skip
	it */

	if ((rseg->id == TRX_SYS_SYSTEM_RSEG_ID)
	    && (UT_LIST_GET_LEN(trx_sys->rseg_list) > 1)) {
		goto loop;
	}

	trx_sys->latest_rseg = rseg;

	return(rseg->id);
}
Exemple #10
0
/**********************************************************************
Validates the flush list. */
static
ibool
buf_flush_validate_low(void)
/*========================*/
		/* out: TRUE if ok */
{
	buf_block_t*	block;
	dulint		om;

	UT_LIST_VALIDATE(flush_list, buf_block_t, buf_pool->flush_list);

	block = UT_LIST_GET_FIRST(buf_pool->flush_list);

	while (block != NULL) {
		om = block->oldest_modification;
		ut_a(block->state == BUF_BLOCK_FILE_PAGE);
		ut_a(ut_dulint_cmp(om, ut_dulint_zero) > 0);

		block = UT_LIST_GET_NEXT(flush_list, block);

		if (block) {
			ut_a(ut_dulint_cmp(om, block->oldest_modification)
			     >= 0);
		}
	}

	return(TRUE);
}
Exemple #11
0
ulint
rw_lock_n_locked(void)
/*==================*/
{
#ifndef UNIV_SYNC_DEBUG
    printf(
        "Sorry, cannot give rw-lock info in non-debug version!\n");
    ut_error;
    return(0);
#else
    rw_lock_t*	lock;
    ulint		count		= 0;

    mutex_enter(&rw_lock_list_mutex);

    lock = UT_LIST_GET_FIRST(rw_lock_list);

    while (lock != NULL) {
        mutex_enter(rw_lock_get_mutex(lock));

        if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
                || (rw_lock_get_reader_count(lock) != 0)) {
            count++;
        }

        mutex_exit(rw_lock_get_mutex(lock));
        lock = UT_LIST_GET_NEXT(list, lock);
    }

    mutex_exit(&rw_lock_list_mutex);

    return(count);
#endif
}
Exemple #12
0
void
rw_lock_print(
    /*==========*/
    rw_lock_t*	lock)	/* in: rw-lock */
{
#ifndef UNIV_SYNC_DEBUG
    printf(
        "Sorry, cannot give rw-lock info in non-debug version!\n");
#else
    ulint		count		= 0;
    rw_lock_debug_t* info;

    printf("-------------\n");
    printf("RW-LATCH INFO\n");
    printf("RW-LATCH: %lx ", (ulint)lock);

    if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
            || (rw_lock_get_reader_count(lock) != 0)
            || (rw_lock_get_waiters(lock) != 0)) {

        if (rw_lock_get_waiters(lock)) {
            printf(" Waiters for the lock exist\n");
        } else {
            printf("\n");
        }

        info = UT_LIST_GET_FIRST(lock->debug_list);
        while (info != NULL) {
            rw_lock_debug_print(info);
            info = UT_LIST_GET_NEXT(list, info);
        }
    }
#endif
}
void OSEventThread::processReadReadies(fd_set * rfds, int n)
{
    TRACE("~~~~ +processReadReadies (%d) ~~~~\n", n);

    OSMutexLocker _locker(&mMutex);
    event_req_t* rev = UT_LIST_GET_FIRST(mWatchList);
    event_req_t* next;
    
    while((NULL != rev) && (n > 0)){
        next = UT_LIST_GET_NEXT(watchNode,rev);
        if (FD_ISSET(rev->fd, rfds)) {
            rev->status = 1;
            UT_LIST_ADD_FIRST(activeNode,mPendingList,rev);
            
            if (rev->persist == false) {
                removeWatch(rev);
                DecreaseWatchNum();
            }
            n--;
        }
        rev = next;
    }

    TRACE("~~~~ -processReadReadies (%d) ~~~~\n", n);
}
void OSEventThread::processTimeouts()
{
    TRACE("~~~~ +processTimeouts ~~~~\n");
    ULONG  now = OS::GetTickCount();

    OSMutexLocker _locker(&mMutex);
    event_timer_t * tev = UT_LIST_GET_FIRST(mTimerList);
    event_timer_t * next;

    // walk list, see if now >= ev->timeout for any events
    TRACE("~~~~ Looking for timers <= %lu ~~~~\n", (unsigned long)now);
    while ((tev) && (now > tev->timeout)) {
        // Timer expired
        TRACE("~~~~ firing timer ~~~~\n");
        next = UT_LIST_GET_NEXT(watchNode,tev);
        
        tev->status = 1;
        UT_LIST_ADD_FIRST(activeNode,mTimeoutList,tev);

        if (tev->persist == false){
            UT_LIST_REMOVE(watchNode,mTimerList,tev);
            //if(tev != &mIdleTimer)
            DecreaseWatchNum();
        }
        
        tev = next;
    }

    TRACE("~~~~ -processTimeouts ~~~~\n");
}
Exemple #15
0
/****************************************************************//**
Inserts the trx handle in the trx system trx list in the right position.
The list is sorted on the trx id so that the biggest id is at the list
start. This function is used at the database startup to insert incomplete
transactions to the list. */
static
void
trx_list_insert_ordered(
/*====================*/
	trx_t*	trx)	/*!< in: trx handle */
{
	trx_t*	trx2;

	ut_ad(mutex_own(&kernel_mutex));

	trx2 = UT_LIST_GET_FIRST(trx_sys->trx_list);

	while (trx2 != NULL) {
		if (ut_dulint_cmp(trx->id, trx2->id) >= 0) {

			ut_ad(ut_dulint_cmp(trx->id, trx2->id) == 1);
			break;
		}
		trx2 = UT_LIST_GET_NEXT(trx_list, trx2);
	}

	if (trx2 != NULL) {
		trx2 = UT_LIST_GET_PREV(trx_list, trx2);

		if (trx2 == NULL) {
			UT_LIST_ADD_FIRST(trx_list, trx_sys->trx_list, trx);
		} else {
			UT_LIST_INSERT_AFTER(trx_list, trx_sys->trx_list,
					     trx2, trx);
		}
	} else {
		UT_LIST_ADD_LAST(trx_list, trx_sys->trx_list, trx);
	}
}
Exemple #16
0
/***************************************************************//**
Returns the number of currently locked rw-locks. Works only in the debug
version.
@return	number of locked rw-locks */
UNIV_INTERN
ulint
rw_lock_n_locked(void)
/*==================*/
{
	rw_lock_t*	lock;
	ulint		count		= 0;

	mutex_enter(&rw_lock_list_mutex);

	lock = UT_LIST_GET_FIRST(rw_lock_list);

	while (lock != NULL) {

		if (lock->lock_word != X_LOCK_DECR) {
			count++;
		}

		lock = UT_LIST_GET_NEXT(list, lock);
	}

	mutex_exit(&rw_lock_list_mutex);

	return(count);
}
Exemple #17
0
ulint
buf_LRU_get_recent_limit(void)
/*==========================*/
			/* out: the limit; zero if could not determine it */
{
	buf_block_t*	block;
	ulint		len;
	ulint		limit;

	mutex_enter(&(buf_pool->mutex));

	len = UT_LIST_GET_LEN(buf_pool->LRU);

	if (len < BUF_LRU_OLD_MIN_LEN) {
		/* The LRU list is too short to do read-ahead */

		mutex_exit(&(buf_pool->mutex));

		return(0);
	}

	block = UT_LIST_GET_FIRST(buf_pool->LRU);

	limit = block->LRU_position - len / BUF_LRU_INITIAL_RATIO;

	mutex_exit(&(buf_pool->mutex));

	return(limit);
}
Exemple #18
0
/**********************************************************************//**
Frees in shutdown all allocated memory not freed yet. */
UNIV_INTERN
void
ut_free_all_mem(void)
/*=================*/
{
	ut_mem_block_t* block;

	ut_a(ut_mem_block_list_inited);
	ut_mem_block_list_inited = FALSE;
	os_fast_mutex_free(&ut_list_mutex);

	while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) {

		ut_a(block->magic_n == UT_MEM_MAGIC_N);
		ut_a(ut_total_allocated_memory >= block->size);

		ut_total_allocated_memory -= block->size;

		UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
		free(block);
	}

	if (ut_total_allocated_memory != 0) {
		fprintf(stderr,
			"InnoDB: Warning: after shutdown"
			" total allocated memory is %lu\n",
			(ulong) ut_total_allocated_memory);
	}

	ut_mem_block_list_inited = FALSE;
}
Exemple #19
0
/*******************************************************************//**
Frees savepoint structs starting from savep, if savep == NULL then
free all savepoints. */
UNIV_INTERN
void
trx_roll_savepoints_free(
/*=====================*/
	trx_t*			trx,	/*!< in: transaction handle */
	trx_named_savept_t*	savep)	/*!< in: free all savepoints > this one;
					if this is NULL, free all savepoints
					of trx */
{
	trx_named_savept_t*	next_savep;

	if (savep == NULL) {
		savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
	} else {
		savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
	}

	while (savep != NULL) {
		next_savep = UT_LIST_GET_NEXT(trx_savepoints, savep);

		trx_roll_savepoint_free(trx, savep);

		savep = next_savep;
	}
}
Exemple #20
0
ulint
rw_lock_n_locked(void)
/*==================*/
{
    rw_lock_t*	lock;
    ulint		count		= 0;

    mutex_enter(&rw_lock_list_mutex);

    lock = UT_LIST_GET_FIRST(rw_lock_list);

    while (lock != NULL) {
        mutex_enter(rw_lock_get_mutex(lock));

        if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
                || (rw_lock_get_reader_count(lock) != 0)) {
            count++;
        }

        mutex_exit(rw_lock_get_mutex(lock));
        lock = UT_LIST_GET_NEXT(list, lock);
    }

    mutex_exit(&rw_lock_list_mutex);

    return(count);
}
Exemple #21
0
void
rw_lock_print(
    /*==========*/
    rw_lock_t*	lock)	/* in: rw-lock */
{
    rw_lock_debug_t* info;

    fprintf(stderr,
            "-------------\n"
            "RW-LATCH INFO\n"
            "RW-LATCH: %p ", (void*) lock);

    if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
            || (rw_lock_get_reader_count(lock) != 0)
            || (rw_lock_get_waiters(lock) != 0)) {

        if (rw_lock_get_waiters(lock)) {
            fputs(" Waiters for the lock exist\n", stderr);
        } else {
            putc('\n', stderr);
        }

        info = UT_LIST_GET_FIRST(lock->debug_list);
        while (info != NULL) {
            rw_lock_debug_print(info);
            info = UT_LIST_GET_NEXT(list, info);
        }
    }
}
Exemple #22
0
ibool
rw_lock_own(
    /*========*/
    /* out: TRUE if locked */
    rw_lock_t*	lock,		/* in: rw-lock */
    ulint		lock_type)	/* in: lock type: RW_LOCK_SHARED,
					RW_LOCK_EX */
{
    rw_lock_debug_t*	info;

    ut_ad(lock);
    ut_ad(rw_lock_validate(lock));

    mutex_enter(&(lock->mutex));

    info = UT_LIST_GET_FIRST(lock->debug_list);

    while (info != NULL) {

        if (os_thread_eq(info->thread_id, os_thread_get_curr_id())
                && (info->pass == 0)
                && (info->lock_type == lock_type)) {

            mutex_exit(&(lock->mutex));
            /* Found! */

            return(TRUE);
        }

        info = UT_LIST_GET_NEXT(list, info);
    }
    mutex_exit(&(lock->mutex));

    return(FALSE);
}
Exemple #23
0
void
buf_flush_insert_sorted_into_flush_list(
/*====================================*/
	buf_block_t*	block)	/* in: block which is modified */
{
	buf_block_t*	prev_b;
	buf_block_t*	b;

	ut_ad(mutex_own(&(buf_pool->mutex)));

	prev_b = NULL;
	b = UT_LIST_GET_FIRST(buf_pool->flush_list);

	while (b && (ut_dulint_cmp(b->oldest_modification,
				   block->oldest_modification) > 0)) {
		prev_b = b;
		b = UT_LIST_GET_NEXT(flush_list, b);
	}

	if (prev_b == NULL) {
		UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block);
	} else {
		UT_LIST_INSERT_AFTER(flush_list, buf_pool->flush_list, prev_b,
				     block);
	}

	ut_ad(buf_flush_validate_low());
}
Exemple #24
0
void
buf_flush_insert_into_flush_list(
/*=============================*/
	buf_block_t*	block)	/* in: block which is modified */
{
	ut_ad(mutex_own(&(buf_pool->mutex)));
	ut_a(block->state == BUF_BLOCK_FILE_PAGE);

	ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL)
	      || (ut_dulint_cmp((UT_LIST_GET_FIRST(buf_pool->flush_list))
				->oldest_modification,
				block->oldest_modification) <= 0));

	UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block);

	ut_ad(buf_flush_validate_low());
}
Exemple #25
0
/*******************************************************************//**
Rolls back a transaction back to a named savepoint. Modifications after the
savepoint are undone but InnoDB does NOT release the corresponding locks
which are stored in memory. If a lock is 'implicit', that is, a new inserted
row holds a lock where the lock information is carried by the trx id stored in
the row, these locks are naturally released in the rollback. Savepoints which
were set after this savepoint are deleted.
@return if no savepoint of the name found then DB_NO_SAVEPOINT,
otherwise DB_SUCCESS */
UNIV_INTERN
ulint
trx_rollback_to_savepoint_for_mysql(
/*================================*/
	trx_t*		trx,			/*!< in: transaction handle */
	const char*	savepoint_name,		/*!< in: savepoint name */
	ib_int64_t*	mysql_binlog_cache_pos)	/*!< out: the MySQL binlog cache
						position corresponding to this
						savepoint; MySQL needs this
						information to remove the
						binlog entries of the queries
						executed after the savepoint */
{
	trx_named_savept_t*	savep;
	ulint			err;

	savep = UT_LIST_GET_FIRST(trx->trx_savepoints);

	while (savep != NULL) {
		if (0 == ut_strcmp(savep->name, savepoint_name)) {
			/* Found */
			break;
		}
		savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
	}

	if (savep == NULL) {

		return(DB_NO_SAVEPOINT);
	}

	if (trx->conc_state == TRX_NOT_STARTED) {
		ut_print_timestamp(stderr);
		fputs("  InnoDB: Error: transaction has a savepoint ", stderr);
		ut_print_name(stderr, trx, FALSE, savep->name);
		fputs(" though it is not started\n", stderr);
		return(DB_ERROR);
	}

	/* We can now free all savepoints strictly later than this one */

	trx_roll_savepoints_free(trx, savep);

	*mysql_binlog_cache_pos = savep->mysql_binlog_cache_pos;

	trx->op_info = "rollback to a savepoint";

	err = trx_general_rollback_for_mysql(trx, &savep->savept);

	/* Store the current undo_no of the transaction so that we know where
	to roll back if we have to roll back the next SQL statement: */

	trx_mark_sql_stat_end(trx);

	trx->op_info = "";

	return(err);
}
Exemple #26
0
void
buf_LRU_print(void)
/*===============*/
{
	buf_block_t*	block;
	buf_frame_t*	frame;
	ulint		len;

	ut_ad(buf_pool);
	mutex_enter(&(buf_pool->mutex));

	fprintf(stderr, "Pool ulint clock %lu\n",
		(ulong) buf_pool->ulint_clock);

	block = UT_LIST_GET_FIRST(buf_pool->LRU);

	len = 0;

	while (block != NULL) {

		fprintf(stderr, "BLOCK %lu ", (ulong) block->offset);

		if (block->old) {
			fputs("old ", stderr);
		}

		if (block->buf_fix_count) {
			fprintf(stderr, "buffix count %lu ",
				(ulong) block->buf_fix_count);
		}

		if (block->io_fix) {
			fprintf(stderr, "io_fix %lu ", (ulong) block->io_fix);
		}

		if (ut_dulint_cmp(block->oldest_modification,
				  ut_dulint_zero) > 0) {
			fputs("modif. ", stderr);
		}

		frame = buf_block_get_frame(block);

		fprintf(stderr, "LRU pos %lu type %lu index id %lu ",
			(ulong) block->LRU_position,
			(ulong) fil_page_get_type(frame),
			(ulong) ut_dulint_get_low
			(btr_page_get_index_id(frame)));

		block = UT_LIST_GET_NEXT(LRU, block);
		if (++len == 10) {
			len = 0;
			putc('\n', stderr);
		}
	}

	mutex_exit(&(buf_pool->mutex));
}
/***************************************************************//**
Creates an index tree for the index if it is not a member of a cluster.
@return	DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
static
ulint
dict_create_index_tree_step(
/*========================*/
	ind_node_t*	node)	/*!< in: index create node */
{
	dict_index_t*	index;
	dict_table_t*	sys_indexes;
	dict_table_t*	table;
	dtuple_t*	search_tuple;
	ulint		zip_size;
	btr_pcur_t	pcur;
	mtr_t		mtr;

	ut_ad(mutex_own(&(dict_sys->mutex)));

	index = node->index;
	table = node->table;

	sys_indexes = dict_sys->sys_indexes;

	/* Run a mini-transaction in which the index tree is allocated for
	the index and its root address is written to the index entry in
	sys_indexes */

	mtr_start(&mtr);

	search_tuple = dict_create_search_tuple(node->ind_row, node->heap);

	btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
		      search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
		      &pcur, &mtr);

	btr_pcur_move_to_next_user_rec(&pcur, &mtr);

	zip_size = dict_table_zip_size(index->table);

	node->page_no = btr_create(index->type, index->space, zip_size,
				   index->id, index, &mtr);
	/* printf("Created a new index tree in space %lu root page %lu\n",
	index->space, index->page_no); */

	page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
				     DICT_SYS_INDEXES_PAGE_NO_FIELD,
				     node->page_no, &mtr);
	btr_pcur_close(&pcur);
	mtr_commit(&mtr);

	if (node->page_no == FIL_NULL) {

		return(DB_OUT_OF_FILE_SPACE);
	}

	return(DB_SUCCESS);
}
/***********************************************************************//**
Free's an instance of the rollback segment in memory. */
UNIV_INTERN
void
trx_rseg_mem_free(
/*==============*/
	trx_rseg_t*	rseg)	/* in, own: instance to free */
{
	trx_undo_t*	undo;

	mutex_free(&rseg->mutex);

	if (!srv_apply_log_only) {
	/* There can't be any active transactions. */
	ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0);
	ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0);
	}

	undo = UT_LIST_GET_FIRST(rseg->update_undo_cached);

	while (undo != NULL) {
		trx_undo_t*	prev_undo = undo;

		undo = UT_LIST_GET_NEXT(undo_list, undo);
		UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo);

		trx_undo_mem_free(prev_undo);
	}

	undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached);

	while (undo != NULL) {
		trx_undo_t*	prev_undo = undo;

		undo = UT_LIST_GET_NEXT(undo_list, undo);
		UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo);

		trx_undo_mem_free(prev_undo);
	}

	trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL);

	mem_free(rseg);
}
Exemple #29
0
/*************************************************************************
Checks if possible foreign key constraints hold after a delete of the record
under pcur. NOTE that this function will temporarily commit mtr and lose
pcur position! */
static
ulint
row_upd_check_references_constraints(
/*=================================*/
				/* out: DB_SUCCESS, DB_LOCK_WAIT, or an error
				code */
	btr_pcur_t*	pcur,	/* in: cursor positioned on a record; NOTE: the
				cursor position is lost in this function! */
	dict_table_t*	table,	/* in: table in question */
	dict_index_t*	index,	/* in: index of the cursor */
	que_thr_t*	thr,	/* in: query thread */
	mtr_t*		mtr)	/* in: mtr */
{
	dict_foreign_t*	foreign;
	mem_heap_t*	heap;
	dtuple_t*	entry;
	rec_t*		rec;
	ulint		err;

	rec = btr_pcur_get_rec(pcur);

	heap = mem_heap_create(500);

	entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);

	mtr_commit(mtr);	

	mtr_start(mtr);	
	
	rw_lock_s_lock(&dict_foreign_key_check_lock);	

	foreign = UT_LIST_GET_FIRST(table->referenced_list);

	while (foreign) {
		if (foreign->referenced_index == index) {

			err = row_ins_check_foreign_constraint(FALSE, foreign,
						table, index, entry, thr);
			if (err != DB_SUCCESS) {
				rw_lock_s_unlock(&dict_foreign_key_check_lock);	
				mem_heap_free(heap);

				return(err);
			}
		}

		foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
	}

	rw_lock_s_unlock(&dict_foreign_key_check_lock);	
	mem_heap_free(heap);
	
	return(DB_SUCCESS);
}
/******************************************************************//**
Calling this function is obligatory only if the memory buffer containing
the mutex is freed. Removes a mutex object from the mutex list. The mutex
is checked to be in the reset state. */
UNIV_INTERN
void
mutex_free(
/*=======*/
	mutex_t*	mutex)	/*!< in: mutex */
{
	ut_ad(mutex_validate(mutex));
	ut_a(mutex_get_lock_word(mutex) == 0);
	ut_a(mutex_get_waiters(mutex) == 0);

#ifdef UNIV_MEM_DEBUG
	if (mutex == &mem_hash_mutex) {
		ut_ad(UT_LIST_GET_LEN(mutex_list) == 1);
		ut_ad(UT_LIST_GET_FIRST(mutex_list) == &mem_hash_mutex);
		UT_LIST_REMOVE(list, mutex_list, mutex);
		goto func_exit;
	}
#endif /* UNIV_MEM_DEBUG */

	if (mutex != &mutex_list_mutex
#ifdef UNIV_SYNC_DEBUG
	    && mutex != &sync_thread_mutex
#endif /* UNIV_SYNC_DEBUG */
	    ) {

		mutex_enter(&mutex_list_mutex);

		ut_ad(!UT_LIST_GET_PREV(list, mutex)
		      || UT_LIST_GET_PREV(list, mutex)->magic_n
		      == MUTEX_MAGIC_N);
		ut_ad(!UT_LIST_GET_NEXT(list, mutex)
		      || UT_LIST_GET_NEXT(list, mutex)->magic_n
		      == MUTEX_MAGIC_N);

		UT_LIST_REMOVE(list, mutex_list, mutex);

		mutex_exit(&mutex_list_mutex);
	}

	os_event_free(mutex->event);
#ifdef UNIV_MEM_DEBUG
func_exit:
#endif /* UNIV_MEM_DEBUG */
#if !defined(HAVE_ATOMIC_BUILTINS)
	os_fast_mutex_free(&(mutex->os_fast_mutex));
#endif
	/* If we free the mutex protecting the mutex list (freeing is
	not necessary), we have to reset the magic number AFTER removing
	it from the list. */
#ifdef UNIV_DEBUG
	mutex->magic_n = 0;
#endif /* UNIV_DEBUG */
}