Commit b0a67daf authored by Satya B's avatar Satya B

Applying InnoDB Plugin 1.0.5 snapshot , part 5

From revision r5733 to r5747

Detailed revision comments:

r5733 | sunny | 2009-09-02 02:05:15 -0500 (Wed, 02 Sep 2009) | 6 lines
branches/zip: Fix a regression introduced by the fix for bug#26316. We check
whether a transaction holds any AUTOINC locks before we acquire the kernel
mutex and release those locks.

Fix for rb://153. Approved by Marko.

r5734 | sunny | 2009-09-02 02:08:45 -0500 (Wed, 02 Sep 2009) | 2 lines
branches/zip: Update ChangeLog with r5733 changes.

r5735 | marko | 2009-09-02 02:43:09 -0500 (Wed, 02 Sep 2009) | 2 lines
branches/zip: univ.i: Do not undefine PACKAGE or VERSION.
InnoDB source code does not refer to these macros.
r5736 | marko | 2009-09-02 02:53:19 -0500 (Wed, 02 Sep 2009) | 1 line
branches/zip: Enclose some timestamp functions in #ifndef UNIV_HOTBACKUP.
r5743 | marko | 2009-09-03 01:36:12 -0500 (Thu, 03 Sep 2009) | 3 lines
branches/zip: log_reserve_and_write_fast(): Remove the redundant
output parameter "success".
Success is also indicated by a nonzero return value.
r5744 | marko | 2009-09-03 03:28:35 -0500 (Thu, 03 Sep 2009) | 1 line
branches/zip: ut_align(): Make ptr const, like in ut_align_down().
r5745 | marko | 2009-09-03 03:38:22 -0500 (Thu, 03 Sep 2009) | 2 lines
branches/zip: log_check_log_recs(): Enclose in #ifdef UNIV_LOG_DEBUG.
Add const qualifiers.
r5746 | marko | 2009-09-03 03:55:36 -0500 (Thu, 03 Sep 2009) | 2 lines
branches/zip: log_reserve_and_write_fast(): Do not cache the log_sys pointer
in a local variable.
r5747 | marko | 2009-09-03 05:46:38 -0500 (Thu, 03 Sep 2009) | 2 lines
branches/zip: recv_scan_log_recs(): Replace while with do...while,
because the termination condition will always hold on the first iteration.
parent 7f890ab6
2009-09-02 The InnoDB Team
* include/lock0lock.h, include/row0mysql.h, lock/lock0lock.c,
row/row0mysql.c:
Fix a regression introduced by the fix for MySQL bug#26316. We check
whether a transaction holds any AUTOINC locks before we acquire
the kernel mutex and release those locks.
2009-08-27 The InnoDB Team 2009-08-27 The InnoDB Team
* dict/dict0dict.c, include/dict0dict.h, * dict/dict0dict.c, include/dict0dict.h,
......
...@@ -630,6 +630,14 @@ lock_number_of_rows_locked( ...@@ -630,6 +630,14 @@ lock_number_of_rows_locked(
/*=======================*/ /*=======================*/
trx_t* trx); /*!< in: transaction */ trx_t* trx); /*!< in: transaction */
/*******************************************************************//** /*******************************************************************//**
Check if a transaction holds any autoinc locks.
@return TRUE if the transaction holds any AUTOINC locks. */
UNIV_INTERN
ibool
lock_trx_holds_autoinc_locks(
/*=========================*/
const trx_t* trx); /*!< in: transaction */
/*******************************************************************//**
Release all the transaction's autoinc locks. */ Release all the transaction's autoinc locks. */
UNIV_INTERN UNIV_INTERN
void void
......
...@@ -118,10 +118,9 @@ UNIV_INLINE ...@@ -118,10 +118,9 @@ UNIV_INLINE
ib_uint64_t ib_uint64_t
log_reserve_and_write_fast( log_reserve_and_write_fast(
/*=======================*/ /*=======================*/
byte* str, /*!< in: string */ const void* str, /*!< in: string */
ulint len, /*!< in: string length */ ulint len, /*!< in: string length */
ib_uint64_t* start_lsn,/*!< out: start lsn of the log record */ ib_uint64_t* start_lsn);/*!< out: start lsn of the log record */
ibool* success);/*!< out: TRUE if success */
/***********************************************************************//** /***********************************************************************//**
Releases the log mutex. */ Releases the log mutex. */
UNIV_INLINE UNIV_INLINE
......
...@@ -27,6 +27,7 @@ Created 12/9/1995 Heikki Tuuri ...@@ -27,6 +27,7 @@ Created 12/9/1995 Heikki Tuuri
#include "mach0data.h" #include "mach0data.h"
#include "mtr0mtr.h" #include "mtr0mtr.h"
#ifdef UNIV_LOG_DEBUG
/******************************************************//** /******************************************************//**
Checks by parsing that the catenated log segment for a single mtr is Checks by parsing that the catenated log segment for a single mtr is
consistent. */ consistent. */
...@@ -34,11 +35,12 @@ UNIV_INTERN ...@@ -34,11 +35,12 @@ UNIV_INTERN
ibool ibool
log_check_log_recs( log_check_log_recs(
/*===============*/ /*===============*/
byte* buf, /*!< in: pointer to the start of const byte* buf, /*!< in: pointer to the start of
the log segment in the the log segment in the
log_sys->buf log buffer */ log_sys->buf log buffer */
ulint len, /*!< in: segment length in bytes */ ulint len, /*!< in: segment length in bytes */
ib_uint64_t buf_start_lsn); /*!< in: buffer start lsn */ ib_uint64_t buf_start_lsn); /*!< in: buffer start lsn */
#endif /* UNIV_LOG_DEBUG */
/************************************************************//** /************************************************************//**
Gets a log block flush bit. Gets a log block flush bit.
...@@ -305,53 +307,49 @@ UNIV_INLINE ...@@ -305,53 +307,49 @@ UNIV_INLINE
ib_uint64_t ib_uint64_t
log_reserve_and_write_fast( log_reserve_and_write_fast(
/*=======================*/ /*=======================*/
byte* str, /*!< in: string */ const void* str, /*!< in: string */
ulint len, /*!< in: string length */ ulint len, /*!< in: string length */
ib_uint64_t* start_lsn,/*!< out: start lsn of the log record */ ib_uint64_t* start_lsn)/*!< out: start lsn of the log record */
ibool* success)/*!< out: TRUE if success */
{ {
log_t* log = log_sys;
ulint data_len; ulint data_len;
ib_uint64_t lsn; ib_uint64_t lsn;
*success = TRUE; mutex_enter(&log_sys->mutex);
mutex_enter(&(log->mutex));
data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE; data_len = len + log_sys->buf_free % OS_FILE_LOG_BLOCK_SIZE;
if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
/* The string does not fit within the current log block /* The string does not fit within the current log block
or the log block would become full */ or the log block would become full */
*success = FALSE; mutex_exit(&log_sys->mutex);
mutex_exit(&(log->mutex));
return(0); return(0);
} }
*start_lsn = log->lsn; *start_lsn = log_sys->lsn;
ut_memcpy(log->buf + log->buf_free, str, len); ut_memcpy(log_sys->buf + log_sys->buf_free, str, len);
log_block_set_data_len((byte*) ut_align_down(log->buf + log->buf_free, log_block_set_data_len((byte*) ut_align_down(log_sys->buf
+ log_sys->buf_free,
OS_FILE_LOG_BLOCK_SIZE), OS_FILE_LOG_BLOCK_SIZE),
data_len); data_len);
#ifdef UNIV_LOG_DEBUG #ifdef UNIV_LOG_DEBUG
log->old_buf_free = log->buf_free; log_sys->old_buf_free = log_sys->buf_free;
log->old_lsn = log->lsn; log_sys->old_lsn = log_sys->lsn;
#endif #endif
log->buf_free += len; log_sys->buf_free += len;
ut_ad(log->buf_free <= log->buf_size); ut_ad(log_sys->buf_free <= log_sys->buf_size);
lsn = log->lsn += len; lsn = log_sys->lsn += len;
#ifdef UNIV_LOG_DEBUG #ifdef UNIV_LOG_DEBUG
log_check_log_recs(log->buf + log->old_buf_free, log_check_log_recs(log_sys->buf + log_sys->old_buf_free,
log->buf_free - log->old_buf_free, log->old_lsn); log_sys->buf_free - log_sys->old_buf_free,
log_sys->old_lsn);
#endif #endif
return(lsn); return(lsn);
} }
......
...@@ -177,7 +177,9 @@ row_update_prebuilt_trx( ...@@ -177,7 +177,9 @@ row_update_prebuilt_trx(
in MySQL handle */ in MySQL handle */
trx_t* trx); /*!< in: transaction handle */ trx_t* trx); /*!< in: transaction handle */
/*********************************************************************//** /*********************************************************************//**
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */ Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
function should be called at the the end of an SQL statement, by the
connection thread that owns the transaction (trx->mysql_thd). */
UNIV_INTERN UNIV_INTERN
void void
row_unlock_table_autoinc_for_mysql( row_unlock_table_autoinc_for_mysql(
......
...@@ -111,14 +111,11 @@ if we are compiling on Windows. */ ...@@ -111,14 +111,11 @@ if we are compiling on Windows. */
# include <sys/mman.h> /* mmap() for os0proc.c */ # include <sys/mman.h> /* mmap() for os0proc.c */
# endif # endif
# undef PACKAGE
# undef VERSION
/* Include the header file generated by GNU autoconf */ /* Include the header file generated by GNU autoconf */
# ifndef __WIN__ # ifndef __WIN__
#ifndef UNIV_HOTBACKUP # ifndef UNIV_HOTBACKUP
# include "config.h" # include "config.h"
#endif /* UNIV_HOTBACKUP */ # endif /* UNIV_HOTBACKUP */
# endif # endif
# ifdef HAVE_SCHED_H # ifdef HAVE_SCHED_H
......
...@@ -219,8 +219,8 @@ UNIV_INLINE ...@@ -219,8 +219,8 @@ UNIV_INLINE
void* void*
ut_align( ut_align(
/*=====*/ /*=====*/
void* ptr, /*!< in: pointer */ const void* ptr, /*!< in: pointer */
ulint align_no); /*!< in: align by this number */ ulint align_no); /*!< in: align by this number */
/*********************************************************//** /*********************************************************//**
The following function rounds down a pointer to the nearest The following function rounds down a pointer to the nearest
aligned address. aligned address.
......
...@@ -319,8 +319,8 @@ UNIV_INLINE ...@@ -319,8 +319,8 @@ UNIV_INLINE
void* void*
ut_align( ut_align(
/*=====*/ /*=====*/
void* ptr, /*!< in: pointer */ const void* ptr, /*!< in: pointer */
ulint align_no) /*!< in: align by this number */ ulint align_no) /*!< in: align by this number */
{ {
ut_ad(align_no > 0); ut_ad(align_no > 0);
ut_ad(((align_no - 1) & align_no) == 0); ut_ad(((align_no - 1) & align_no) == 0);
......
...@@ -216,6 +216,7 @@ UNIV_INTERN ...@@ -216,6 +216,7 @@ UNIV_INTERN
ib_time_t ib_time_t
ut_time(void); ut_time(void);
/*=========*/ /*=========*/
#ifndef UNIV_HOTBACKUP
/**********************************************************//** /**********************************************************//**
Returns system time. Returns system time.
Upon successful completion, the value 0 is returned; otherwise the Upon successful completion, the value 0 is returned; otherwise the
...@@ -248,6 +249,7 @@ UNIV_INTERN ...@@ -248,6 +249,7 @@ UNIV_INTERN
uint uint
ut_time_ms(void); ut_time_ms(void);
/*============*/ /*============*/
#endif /* !UNIV_HOTBACKUP */
/**********************************************************//** /**********************************************************//**
Returns the difference of two times in seconds. Returns the difference of two times in seconds.
......
...@@ -5371,6 +5371,20 @@ lock_release_autoinc_last_lock( ...@@ -5371,6 +5371,20 @@ lock_release_autoinc_last_lock(
lock_table_dequeue(lock); lock_table_dequeue(lock);
} }
/*******************************************************************//**
Check if a transaction holds any autoinc locks.
@return TRUE if the transaction holds any AUTOINC locks. */
UNIV_INTERN
ibool
lock_trx_holds_autoinc_locks(
/*=========================*/
const trx_t* trx) /*!< in: transaction */
{
ut_a(trx->autoinc_locks != NULL);
return(!ib_vector_is_empty(trx->autoinc_locks));
}
/*******************************************************************//** /*******************************************************************//**
Release all the transaction's autoinc locks. */ Release all the transaction's autoinc locks. */
UNIV_INTERN UNIV_INTERN
......
...@@ -3234,6 +3234,7 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3234,6 +3234,7 @@ logs_empty_and_mark_files_at_shutdown(void)
ut_a(lsn == log_sys->lsn); ut_a(lsn == log_sys->lsn);
} }
#ifdef UNIV_LOG_DEBUG
/******************************************************//** /******************************************************//**
Checks by parsing that the catenated log segment for a single mtr is Checks by parsing that the catenated log segment for a single mtr is
consistent. */ consistent. */
...@@ -3241,7 +3242,7 @@ UNIV_INTERN ...@@ -3241,7 +3242,7 @@ UNIV_INTERN
ibool ibool
log_check_log_recs( log_check_log_recs(
/*===============*/ /*===============*/
byte* buf, /*!< in: pointer to the start of const byte* buf, /*!< in: pointer to the start of
the log segment in the the log segment in the
log_sys->buf log buffer */ log_sys->buf log buffer */
ulint len, /*!< in: segment length in bytes */ ulint len, /*!< in: segment length in bytes */
...@@ -3249,8 +3250,8 @@ log_check_log_recs( ...@@ -3249,8 +3250,8 @@ log_check_log_recs(
{ {
ib_uint64_t contiguous_lsn; ib_uint64_t contiguous_lsn;
ib_uint64_t scanned_lsn; ib_uint64_t scanned_lsn;
byte* start; const byte* start;
byte* end; const byte* end;
byte* buf1; byte* buf1;
byte* scan_buf; byte* scan_buf;
...@@ -3283,6 +3284,7 @@ log_check_log_recs( ...@@ -3283,6 +3284,7 @@ log_check_log_recs(
return(TRUE); return(TRUE);
} }
#endif /* UNIV_LOG_DEBUG */
/******************************************************//** /******************************************************//**
Peeks the current lsn. Peeks the current lsn.
......
...@@ -2415,8 +2415,7 @@ recv_scan_log_recs( ...@@ -2415,8 +2415,7 @@ recv_scan_log_recs(
scanned_lsn = start_lsn; scanned_lsn = start_lsn;
more_data = FALSE; more_data = FALSE;
while (log_block < buf + len && !finished) { do {
no = log_block_get_hdr_no(log_block); no = log_block_get_hdr_no(log_block);
/* /*
fprintf(stderr, "Log block header no %lu\n", no); fprintf(stderr, "Log block header no %lu\n", no);
...@@ -2546,10 +2545,11 @@ recv_scan_log_recs( ...@@ -2546,10 +2545,11 @@ recv_scan_log_recs(
/* Log data for this group ends here */ /* Log data for this group ends here */
finished = TRUE; finished = TRUE;
break;
} else { } else {
log_block += OS_FILE_LOG_BLOCK_SIZE; log_block += OS_FILE_LOG_BLOCK_SIZE;
} }
} } while (log_block < buf + len && !finished);
*group_scanned_lsn = scanned_lsn; *group_scanned_lsn = scanned_lsn;
......
...@@ -115,7 +115,6 @@ mtr_log_reserve_and_write( ...@@ -115,7 +115,6 @@ mtr_log_reserve_and_write(
dyn_array_t* mlog; dyn_array_t* mlog;
dyn_block_t* block; dyn_block_t* block;
ulint data_size; ulint data_size;
ibool success;
byte* first_data; byte* first_data;
ut_ad(mtr); ut_ad(mtr);
...@@ -134,8 +133,8 @@ mtr_log_reserve_and_write( ...@@ -134,8 +133,8 @@ mtr_log_reserve_and_write(
if (mlog->heap == NULL) { if (mlog->heap == NULL) {
mtr->end_lsn = log_reserve_and_write_fast( mtr->end_lsn = log_reserve_and_write_fast(
first_data, dyn_block_get_used(mlog), first_data, dyn_block_get_used(mlog),
&(mtr->start_lsn), &success); &mtr->start_lsn);
if (success) { if (mtr->end_lsn) {
return; return;
} }
......
...@@ -47,8 +47,10 @@ Created June 2005 by Marko Makela ...@@ -47,8 +47,10 @@ Created June 2005 by Marko Makela
# define buf_LRU_stat_inc_unzip() ((void) 0) # define buf_LRU_stat_inc_unzip() ((void) 0)
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
#ifndef UNIV_HOTBACKUP
/** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */ /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1]; UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1];
#endif /* !UNIV_HOTBACKUP */
/* Please refer to ../include/page0zip.ic for a description of the /* Please refer to ../include/page0zip.ic for a description of the
compressed page format. */ compressed page format. */
...@@ -1144,7 +1146,9 @@ page_zip_compress( ...@@ -1144,7 +1146,9 @@ page_zip_compress(
ulint* offsets = NULL; ulint* offsets = NULL;
ulint n_blobs = 0; ulint n_blobs = 0;
byte* storage;/* storage of uncompressed columns */ byte* storage;/* storage of uncompressed columns */
#ifndef UNIV_HOTBACKUP
ullint usec = ut_time_us(NULL); ullint usec = ut_time_us(NULL);
#endif /* !UNIV_HOTBACKUP */
#ifdef PAGE_ZIP_COMPRESS_DBG #ifdef PAGE_ZIP_COMPRESS_DBG
FILE* logfile = NULL; FILE* logfile = NULL;
#endif #endif
...@@ -1208,7 +1212,9 @@ page_zip_compress( ...@@ -1208,7 +1212,9 @@ page_zip_compress(
} }
} }
#endif /* PAGE_ZIP_COMPRESS_DBG */ #endif /* PAGE_ZIP_COMPRESS_DBG */
#ifndef UNIV_HOTBACKUP
page_zip_stat[page_zip->ssize - 1].compressed++; page_zip_stat[page_zip->ssize - 1].compressed++;
#endif /* !UNIV_HOTBACKUP */
if (UNIV_UNLIKELY(n_dense * PAGE_ZIP_DIR_SLOT_SIZE if (UNIV_UNLIKELY(n_dense * PAGE_ZIP_DIR_SLOT_SIZE
>= page_zip_get_size(page_zip))) { >= page_zip_get_size(page_zip))) {
...@@ -1345,8 +1351,10 @@ page_zip_compress( ...@@ -1345,8 +1351,10 @@ page_zip_compress(
fclose(logfile); fclose(logfile);
} }
#endif /* PAGE_ZIP_COMPRESS_DBG */ #endif /* PAGE_ZIP_COMPRESS_DBG */
#ifndef UNIV_HOTBACKUP
page_zip_stat[page_zip->ssize - 1].compressed_usec page_zip_stat[page_zip->ssize - 1].compressed_usec
+= ut_time_us(NULL) - usec; += ut_time_us(NULL) - usec;
#endif /* !UNIV_HOTBACKUP */
return(FALSE); return(FALSE);
} }
...@@ -1404,12 +1412,14 @@ page_zip_compress( ...@@ -1404,12 +1412,14 @@ page_zip_compress(
fclose(logfile); fclose(logfile);
} }
#endif /* PAGE_ZIP_COMPRESS_DBG */ #endif /* PAGE_ZIP_COMPRESS_DBG */
#ifndef UNIV_HOTBACKUP
{ {
page_zip_stat_t* zip_stat page_zip_stat_t* zip_stat
= &page_zip_stat[page_zip->ssize - 1]; = &page_zip_stat[page_zip->ssize - 1];
zip_stat->compressed_ok++; zip_stat->compressed_ok++;
zip_stat->compressed_usec += ut_time_us(NULL) - usec; zip_stat->compressed_usec += ut_time_us(NULL) - usec;
} }
#endif /* !UNIV_HOTBACKUP */
return(TRUE); return(TRUE);
} }
...@@ -2820,7 +2830,9 @@ page_zip_decompress( ...@@ -2820,7 +2830,9 @@ page_zip_decompress(
ulint trx_id_col = ULINT_UNDEFINED; ulint trx_id_col = ULINT_UNDEFINED;
mem_heap_t* heap; mem_heap_t* heap;
ulint* offsets; ulint* offsets;
#ifndef UNIV_HOTBACKUP
ullint usec = ut_time_us(NULL); ullint usec = ut_time_us(NULL);
#endif /* !UNIV_HOTBACKUP */
ut_ad(page_zip_simple_validate(page_zip)); ut_ad(page_zip_simple_validate(page_zip));
UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE); UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE);
...@@ -2976,12 +2988,14 @@ page_zip_decompress( ...@@ -2976,12 +2988,14 @@ page_zip_decompress(
page_zip_fields_free(index); page_zip_fields_free(index);
mem_heap_free(heap); mem_heap_free(heap);
#ifndef UNIV_HOTBACKUP
{ {
page_zip_stat_t* zip_stat page_zip_stat_t* zip_stat
= &page_zip_stat[page_zip->ssize - 1]; = &page_zip_stat[page_zip->ssize - 1];
zip_stat->decompressed++; zip_stat->decompressed++;
zip_stat->decompressed_usec += ut_time_us(NULL) - usec; zip_stat->decompressed_usec += ut_time_us(NULL) - usec;
} }
#endif /* !UNIV_HOTBACKUP */
/* Update the stat counter for LRU policy. */ /* Update the stat counter for LRU policy. */
buf_LRU_stat_inc_unzip(); buf_LRU_stat_inc_unzip();
......
...@@ -866,18 +866,22 @@ row_update_statistics_if_needed( ...@@ -866,18 +866,22 @@ row_update_statistics_if_needed(
} }
/*********************************************************************//** /*********************************************************************//**
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */ Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
function should be called at the the end of an SQL statement, by the
connection thread that owns the transaction (trx->mysql_thd). */
UNIV_INTERN UNIV_INTERN
void void
row_unlock_table_autoinc_for_mysql( row_unlock_table_autoinc_for_mysql(
/*===============================*/ /*===============================*/
trx_t* trx) /*!< in/out: transaction */ trx_t* trx) /*!< in/out: transaction */
{ {
mutex_enter(&kernel_mutex); if (lock_trx_holds_autoinc_locks(trx)) {
mutex_enter(&kernel_mutex);
lock_release_autoinc_locks(trx); lock_release_autoinc_locks(trx);
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
}
} }
/*********************************************************************//** /*********************************************************************//**
......
...@@ -132,6 +132,7 @@ ut_time(void) ...@@ -132,6 +132,7 @@ ut_time(void)
return(time(NULL)); return(time(NULL));
} }
#ifndef UNIV_HOTBACKUP
/**********************************************************//** /**********************************************************//**
Returns system time. Returns system time.
Upon successful completion, the value 0 is returned; otherwise the Upon successful completion, the value 0 is returned; otherwise the
...@@ -215,6 +216,7 @@ ut_time_ms(void) ...@@ -215,6 +216,7 @@ ut_time_ms(void)
return((uint) tv.tv_sec * 1000 + tv.tv_usec / 1000); return((uint) tv.tv_sec * 1000 + tv.tv_usec / 1000);
} }
#endif /* !UNIV_HOTBACKUP */
/**********************************************************//** /**********************************************************//**
Returns the difference of two times in seconds. Returns the difference of two times in seconds.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment