Commit 5a90bc1f authored by Bruce Momjian's avatar Bruce Momjian

The attached patch contains a couple of fixes in the existing probes and

includes a few new ones.

- Fixed compilation errors on OS X for probes that use typedefs
- Fixed a number of probes to pass ForkNumber per the relation forks
patch
- The new probes are those that were taken out from the previous
submitted patch and required simple fixes. Will submit the other probes
that may require more discussion in a separate patch.

Robert Lor
parent 5434e469
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.323 2008/12/03 08:20:11 heikki Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.324 2008/12/17 01:39:03 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/guc.h" #include "utils/guc.h"
#include "utils/ps_status.h" #include "utils/ps_status.h"
#include "pg_trace.h"
/* File path names (all relative to $PGDATA) */ /* File path names (all relative to $PGDATA) */
...@@ -486,6 +487,8 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata) ...@@ -486,6 +487,8 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
if (info & XLR_INFO_MASK) if (info & XLR_INFO_MASK)
elog(PANIC, "invalid xlog info mask %02X", info); elog(PANIC, "invalid xlog info mask %02X", info);
TRACE_POSTGRESQL_XLOG_INSERT(rmid, info);
/* /*
* In bootstrap mode, we don't actually log anything but XLOG resources; * In bootstrap mode, we don't actually log anything but XLOG resources;
* return a phony record pointer. * return a phony record pointer.
...@@ -914,6 +917,8 @@ begin:; ...@@ -914,6 +917,8 @@ begin:;
XLogwrtRqst FlushRqst; XLogwrtRqst FlushRqst;
XLogRecPtr OldSegEnd; XLogRecPtr OldSegEnd;
TRACE_POSTGRESQL_XLOG_SWITCH();
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE); LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
/* /*
...@@ -1313,12 +1318,14 @@ AdvanceXLInsertBuffer(bool new_segment) ...@@ -1313,12 +1318,14 @@ AdvanceXLInsertBuffer(bool new_segment)
* Have to write buffers while holding insert lock. This is * Have to write buffers while holding insert lock. This is
* not good, so only write as much as we absolutely must. * not good, so only write as much as we absolutely must.
*/ */
TRACE_POSTGRESQL_WAL_BUFFER_WRITE_START();
WriteRqst.Write = OldPageRqstPtr; WriteRqst.Write = OldPageRqstPtr;
WriteRqst.Flush.xlogid = 0; WriteRqst.Flush.xlogid = 0;
WriteRqst.Flush.xrecoff = 0; WriteRqst.Flush.xrecoff = 0;
XLogWrite(WriteRqst, false, false); XLogWrite(WriteRqst, false, false);
LWLockRelease(WALWriteLock); LWLockRelease(WALWriteLock);
Insert->LogwrtResult = LogwrtResult; Insert->LogwrtResult = LogwrtResult;
TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DONE();
} }
} }
} }
...@@ -5904,6 +5911,8 @@ CreateCheckPoint(int flags) ...@@ -5904,6 +5911,8 @@ CreateCheckPoint(int flags)
if (log_checkpoints) if (log_checkpoints)
LogCheckpointStart(flags); LogCheckpointStart(flags);
TRACE_POSTGRESQL_CHECKPOINT_START(flags);
/* /*
* Before flushing data, we must wait for any transactions that are * Before flushing data, we must wait for any transactions that are
* currently in their commit critical sections. If an xact inserted its * currently in their commit critical sections. If an xact inserted its
...@@ -6069,6 +6078,11 @@ CreateCheckPoint(int flags) ...@@ -6069,6 +6078,11 @@ CreateCheckPoint(int flags)
if (log_checkpoints) if (log_checkpoints)
LogCheckpointEnd(); LogCheckpointEnd();
TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
NBuffers, CheckpointStats.ckpt_segs_added,
CheckpointStats.ckpt_segs_removed,
CheckpointStats.ckpt_segs_recycled);
LWLockRelease(CheckpointLock); LWLockRelease(CheckpointLock);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.242 2008/11/19 10:34:52 heikki Exp $ * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.243 2008/12/17 01:39:03 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -203,8 +203,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, ForkNumber forkNum, ...@@ -203,8 +203,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, ForkNumber forkNum,
if (isExtend) if (isExtend)
blockNum = smgrnblocks(smgr, forkNum); blockNum = smgrnblocks(smgr, forkNum);
TRACE_POSTGRESQL_BUFFER_READ_START(blockNum, smgr->smgr_rnode.spcNode, TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum, smgr->smgr_rnode.spcNode, smgr->smgr_rnode.dbNode, smgr->smgr_rnode.relNode, isLocalBuf);
smgr->smgr_rnode.dbNode, smgr->smgr_rnode.relNode, isLocalBuf);
if (isLocalBuf) if (isLocalBuf)
{ {
...@@ -253,7 +252,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, ForkNumber forkNum, ...@@ -253,7 +252,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, ForkNumber forkNum,
if (VacuumCostActive) if (VacuumCostActive)
VacuumCostBalance += VacuumCostPageHit; VacuumCostBalance += VacuumCostPageHit;
TRACE_POSTGRESQL_BUFFER_READ_DONE(blockNum, TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
smgr->smgr_rnode.spcNode, smgr->smgr_rnode.spcNode,
smgr->smgr_rnode.dbNode, smgr->smgr_rnode.dbNode,
smgr->smgr_rnode.relNode, isLocalBuf, found); smgr->smgr_rnode.relNode, isLocalBuf, found);
...@@ -380,9 +379,9 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, ForkNumber forkNum, ...@@ -380,9 +379,9 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, ForkNumber forkNum,
if (VacuumCostActive) if (VacuumCostActive)
VacuumCostBalance += VacuumCostPageMiss; VacuumCostBalance += VacuumCostPageMiss;
TRACE_POSTGRESQL_BUFFER_READ_DONE(blockNum, smgr->smgr_rnode.spcNode, TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
smgr->smgr_rnode.dbNode, smgr->smgr_rnode.relNode, smgr->smgr_rnode.spcNode, smgr->smgr_rnode.dbNode,
isLocalBuf, found); smgr->smgr_rnode.relNode, isLocalBuf, found);
return BufferDescriptorGetBuffer(bufHdr); return BufferDescriptorGetBuffer(bufHdr);
} }
...@@ -526,6 +525,11 @@ BufferAlloc(SMgrRelation smgr, ForkNumber forkNum, ...@@ -526,6 +525,11 @@ BufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
* happens to be trying to split the page the first one got from * happens to be trying to split the page the first one got from
* StrategyGetBuffer.) * StrategyGetBuffer.)
*/ */
TRACE_POSTGRESQL_BUFFER_WRITE_DIRTY_START(forkNum,
blockNum, smgr->smgr_rnode.spcNode,
smgr->smgr_rnode.dbNode, smgr->smgr_rnode.relNode);
if (LWLockConditionalAcquire(buf->content_lock, LW_SHARED)) if (LWLockConditionalAcquire(buf->content_lock, LW_SHARED))
{ {
/* /*
...@@ -548,6 +552,11 @@ BufferAlloc(SMgrRelation smgr, ForkNumber forkNum, ...@@ -548,6 +552,11 @@ BufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
/* OK, do the I/O */ /* OK, do the I/O */
FlushBuffer(buf, NULL); FlushBuffer(buf, NULL);
LWLockRelease(buf->content_lock); LWLockRelease(buf->content_lock);
TRACE_POSTGRESQL_BUFFER_WRITE_DIRTY_DONE(
forkNum, blockNum, smgr->smgr_rnode.spcNode,
smgr->smgr_rnode.dbNode,
smgr->smgr_rnode.relNode);
} }
else else
{ {
...@@ -1682,6 +1691,7 @@ CheckPointBuffers(int flags) ...@@ -1682,6 +1691,7 @@ CheckPointBuffers(int flags)
CheckpointStats.ckpt_write_t = GetCurrentTimestamp(); CheckpointStats.ckpt_write_t = GetCurrentTimestamp();
BufferSync(flags); BufferSync(flags);
CheckpointStats.ckpt_sync_t = GetCurrentTimestamp(); CheckpointStats.ckpt_sync_t = GetCurrentTimestamp();
TRACE_POSTGRESQL_BUFFER_CHECKPOINT_SYNC_START();
smgrsync(); smgrsync();
CheckpointStats.ckpt_sync_end_t = GetCurrentTimestamp(); CheckpointStats.ckpt_sync_end_t = GetCurrentTimestamp();
TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE(); TRACE_POSTGRESQL_BUFFER_CHECKPOINT_DONE();
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.141 2008/11/14 11:09:50 heikki Exp $ * $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.142 2008/12/17 01:39:04 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/hsearch.h" #include "utils/hsearch.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "pg_trace.h"
/* interval for calling AbsorbFsyncRequests in mdsync */ /* interval for calling AbsorbFsyncRequests in mdsync */
...@@ -560,6 +561,8 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, ...@@ -560,6 +561,8 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
int nbytes; int nbytes;
MdfdVec *v; MdfdVec *v;
TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum, reln->smgr_rnode.spcNode, reln->smgr_rnode.dbNode, reln->smgr_rnode.relNode);
v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL); v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL);
seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)); seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
...@@ -571,7 +574,11 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, ...@@ -571,7 +574,11 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
errmsg("could not seek to block %u of relation %s: %m", errmsg("could not seek to block %u of relation %s: %m",
blocknum, relpath(reln->smgr_rnode, forknum)))); blocknum, relpath(reln->smgr_rnode, forknum))));
if ((nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ) nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ);
TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum, reln->smgr_rnode.spcNode, reln->smgr_rnode.dbNode, reln->smgr_rnode.relNode, relpath(reln->smgr_rnode, forknum), nbytes, BLCKSZ);
if (nbytes != BLCKSZ)
{ {
if (nbytes < 0) if (nbytes < 0)
ereport(ERROR, ereport(ERROR,
...@@ -618,6 +625,8 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, ...@@ -618,6 +625,8 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
Assert(blocknum < mdnblocks(reln, forknum)); Assert(blocknum < mdnblocks(reln, forknum));
#endif #endif
TRACE_POSTGRESQL_SMGR_MD_WRITE_START(forknum, blocknum, reln->smgr_rnode.spcNode, reln->smgr_rnode.dbNode, reln->smgr_rnode.relNode);
v = _mdfd_getseg(reln, forknum, blocknum, isTemp, EXTENSION_FAIL); v = _mdfd_getseg(reln, forknum, blocknum, isTemp, EXTENSION_FAIL);
seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)); seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
...@@ -629,7 +638,11 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, ...@@ -629,7 +638,11 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
errmsg("could not seek to block %u of relation %s: %m", errmsg("could not seek to block %u of relation %s: %m",
blocknum, relpath(reln->smgr_rnode, forknum)))); blocknum, relpath(reln->smgr_rnode, forknum))));
if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ) nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ);
TRACE_POSTGRESQL_SMGR_MD_WRITE_DONE(forknum, blocknum, reln->smgr_rnode.spcNode, reln->smgr_rnode.dbNode, reln->smgr_rnode.relNode, relpath(reln->smgr_rnode, forknum), nbytes, BLCKSZ);
if (nbytes != BLCKSZ)
{ {
if (nbytes < 0) if (nbytes < 0)
ereport(ERROR, ereport(ERROR,
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
# Copyright (c) 2008, PostgreSQL Global Development Group # Copyright (c) 2008, PostgreSQL Global Development Group
# #
# $PostgreSQL: pgsql/src/backend/utils/Gen_dummy_probes.sed,v 1.2 2008/08/01 13:16:09 alvherre Exp $ # $PostgreSQL: pgsql/src/backend/utils/Gen_dummy_probes.sed,v 1.3 2008/12/17 01:39:04 momjian Exp $
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
/^[ ]*probe /!d /^[ ]*probe /!d
...@@ -17,5 +17,7 @@ s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3)/ ...@@ -17,5 +17,7 @@ s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3)/
s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3, INT4)/ s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3, INT4)/
s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3, INT4, INT5)/ s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3, INT4, INT5)/
s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3, INT4, INT5, INT6)/ s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3, INT4, INT5, INT6)/
s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3, INT4, INT5, INT6, INT7)/
s/([^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\}, [^,)]\{1,\})/(INT1, INT2, INT3, INT4, INT5, INT6, INT7, INT8)/
P P
s/(.*$/_ENABLED() (0)/ s/(.*$/_ENABLED() (0)/
...@@ -3,26 +3,25 @@ ...@@ -3,26 +3,25 @@
* *
* Copyright (c) 2006-2008, PostgreSQL Global Development Group * Copyright (c) 2006-2008, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/utils/probes.d,v 1.3 2008/08/01 13:16:09 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/utils/probes.d,v 1.4 2008/12/17 01:39:04 momjian Exp $
* ---------- * ----------
*/ */
/* typedefs used in PostgreSQL */ /* typedefs used in PostgreSQL */
typedef unsigned int LocalTransactionId; #define LocalTransactionId unsigned int
typedef int LWLockId; #define LWLockId int
typedef int LWLockMode; #define LWLockMode int
typedef int LOCKMODE; #define LOCKMODE int
typedef unsigned int BlockNumber; #define BlockNumber unsigned int
typedef unsigned int Oid; #define Oid unsigned int
#define ForkNumber int
#define bool char #define bool char
provider postgresql { provider postgresql {
/* /*
* Due to a bug in Mac OS X 10.5, using built-in typedefs (e.g. uintptr_t, * Note: Do not use built-in typedefs (e.g. uintptr_t, uint32_t, etc) * as they cause compilation errors in Mac OS X 10.5.
* uint32_t, etc.) cause compilation errors.
*/ */
probe transaction__start(LocalTransactionId); probe transaction__start(LocalTransactionId);
...@@ -36,13 +35,8 @@ provider postgresql { ...@@ -36,13 +35,8 @@ provider postgresql {
probe lwlock__condacquire(LWLockId, LWLockMode); probe lwlock__condacquire(LWLockId, LWLockMode);
probe lwlock__condacquire__fail(LWLockId, LWLockMode); probe lwlock__condacquire__fail(LWLockId, LWLockMode);
/* The following probe declarations cause compilation errors probe lock__wait__start(unsigned int, LOCKMODE);
* on Mac OS X but not on Solaris. Need further investigation. probe lock__wait__done(unsigned int, LOCKMODE);
* probe lock__wait__start(unsigned int, LOCKMODE);
* probe lock__wait__done(unsigned int, LOCKMODE);
*/
probe lock__wait__start(unsigned int, int);
probe lock__wait__done(unsigned int, int);
probe query__parse__start(const char *); probe query__parse__start(const char *);
probe query__parse__done(const char *); probe query__parse__done(const char *);
...@@ -59,27 +53,26 @@ provider postgresql { ...@@ -59,27 +53,26 @@ provider postgresql {
probe sort__start(int, bool, int, int, bool); probe sort__start(int, bool, int, int, bool);
probe sort__done(unsigned long, long); probe sort__done(unsigned long, long);
/* The following probe declarations cause compilation errors probe buffer__read__start(ForkNumber, BlockNumber, Oid, Oid, Oid, bool);
* on Mac OS X but not on Solaris. Need further investigation. probe buffer__read__done(ForkNumber, BlockNumber, Oid, Oid, Oid, bool, bool);
* probe buffer__read__start(BlockNumber, Oid, Oid, Oid, bool);
* probe buffer__read__done(BlockNumber, Oid, Oid, Oid, bool, bool);
*/
probe buffer__read__start(unsigned int, unsigned int, unsigned int, unsigned int, bool);
probe buffer__read__done(unsigned int, unsigned int, unsigned int, unsigned int, bool, bool);
probe buffer__flush__start(Oid, Oid, Oid); probe buffer__flush__start(Oid, Oid, Oid);
probe buffer__flush__done(Oid, Oid, Oid); probe buffer__flush__done(Oid, Oid, Oid);
probe buffer__hit(bool); probe buffer__hit(bool);
probe buffer__miss(bool); probe buffer__miss(bool);
probe buffer__checkpoint__start(int); probe buffer__checkpoint__start(int);
probe buffer__checkpoint__sync__start();
probe buffer__checkpoint__done(); probe buffer__checkpoint__done();
probe buffer__sync__start(int, int); probe buffer__sync__start(int, int);
probe buffer__sync__written(int); probe buffer__sync__written(int);
probe buffer__sync__done(int, int, int); probe buffer__sync__done(int, int, int);
probe buffer__write__dirty__start(ForkNumber, BlockNumber, Oid, Oid, Oid);
probe buffer__write__dirty__done(ForkNumber, BlockNumber, Oid, Oid, Oid);
probe deadlock__found(); probe deadlock__found();
probe checkpoint__start(int);
probe checkpoint__done(int, int, int, int, int);
probe clog__checkpoint__start(bool); probe clog__checkpoint__start(bool);
probe clog__checkpoint__done(bool); probe clog__checkpoint__done(bool);
probe subtrans__checkpoint__start(bool); probe subtrans__checkpoint__start(bool);
...@@ -88,4 +81,14 @@ provider postgresql { ...@@ -88,4 +81,14 @@ provider postgresql {
probe multixact__checkpoint__done(bool); probe multixact__checkpoint__done(bool);
probe twophase__checkpoint__start(); probe twophase__checkpoint__start();
probe twophase__checkpoint__done(); probe twophase__checkpoint__done();
probe smgr__md__read__start(ForkNumber, BlockNumber, Oid, Oid, Oid);
probe smgr__md__read__done(ForkNumber, BlockNumber, Oid, Oid, Oid, const char *, int, int);
probe smgr__md__write__start(ForkNumber, BlockNumber, Oid, Oid, Oid);
probe smgr__md__write__done(ForkNumber, BlockNumber, Oid, Oid, Oid, const char *, int, int);
probe xlog__insert(unsigned char, unsigned char);
probe xlog__switch();
probe wal__buffer__write__start();
probe wal__buffer__write__done();
}; };
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