Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
65121806
Commit
65121806
authored
Feb 01, 2014
by
Sergei Golubchik
Browse files
Options
Browse Files
Download
Plain Diff
upgrade sphinx to 2.1.5
parents
325c9cba
01673997
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
81 additions
and
61 deletions
+81
-61
debian/dist/Debian/mariadb-server-10.0.files.in
debian/dist/Debian/mariadb-server-10.0.files.in
+0
-1
debian/dist/Ubuntu/mariadb-server-10.0.files.in
debian/dist/Ubuntu/mariadb-server-10.0.files.in
+0
-1
storage/sphinx/CMakeLists.txt
storage/sphinx/CMakeLists.txt
+10
-10
storage/sphinx/ha_sphinx.cc
storage/sphinx/ha_sphinx.cc
+50
-33
storage/sphinx/ha_sphinx.h
storage/sphinx/ha_sphinx.h
+6
-2
storage/sphinx/make-patch.sh
storage/sphinx/make-patch.sh
+0
-0
storage/sphinx/snippets_udf.cc
storage/sphinx/snippets_udf.cc
+15
-14
No files found.
debian/dist/Debian/mariadb-server-10.0.files.in
View file @
65121806
...
...
@@ -10,7 +10,6 @@ usr/lib/mysql/plugin/query_cache_info.so
usr/lib/mysql/plugin/query_response_time.so
usr/lib/mysql/plugin/semisync_master.so
usr/lib/mysql/plugin/semisync_slave.so
usr/lib/mysql/plugin/sphinx.so
usr/lib/mysql/plugin/sql_errlog.so
usr/lib/libhsclient.so.*
etc/mysql/debian-start
...
...
debian/dist/Ubuntu/mariadb-server-10.0.files.in
View file @
65121806
...
...
@@ -10,7 +10,6 @@ usr/lib/mysql/plugin/query_cache_info.so
usr/lib/mysql/plugin/query_response_time.so
usr/lib/mysql/plugin/semisync_master.so
usr/lib/mysql/plugin/semisync_slave.so
usr/lib/mysql/plugin/sphinx.so
usr/lib/mysql/plugin/sql_errlog.so
usr/lib/libhsclient.so.*
etc/apparmor.d/usr.sbin.mysqld
...
...
storage/sphinx/CMakeLists.txt
View file @
65121806
INCLUDE
(
CheckCCompilerFlag
)
ADD_DEFINITIONS
(
-DMYSQL_SERVER
)
SET
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
-fno-strict-aliasing"
)
CHECK_C_COMPILER_FLAG
(
"-Wno-write-strings"
WNO_WRITE_STRING
)
IF
(
WNO_WRITE_STRING
)
SET
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
-Wno-write-strings"
)
ENDIF
()
IF
(
MSVC
)
LINK_LIBRARIES
(
ws2_32
)
ENDIF
(
MSVC
)
MYSQL_ADD_PLUGIN
(
sphinx ha_sphinx.cc STORAGE_ENGINE
)
IF
(
NOT WITHOUT_SPHINX_STORAGE_ENGINE
)
ADD_LIBRARY
(
snippets_udf MODULE snippets_udf.cc
)
TARGET_LINK_LIBRARIES
(
snippets_udf mysys
)
# my_error
ADD_DEPENDENCIES
(
snippets_udf GenError
)
# uses generated error constants
SET_TARGET_PROPERTIES
(
snippets_udf PROPERTIES OUTPUT_NAME sphinx PREFIX
""
)
INSTALL
(
TARGETS snippets_udf COMPONENT Server DESTINATION
${
INSTALL_PLUGINDIR
}
)
ENDIF
()
SET
(
SPHINX_SOURCES ha_sphinx.cc snippets_udf.cc
)
MYSQL_ADD_PLUGIN
(
sphinx
${
SPHINX_SOURCES
}
STORAGE_ENGINE LINK_LIBRARIES mysys
)
storage/sphinx/ha_sphinx.cc
View file @
65121806
//
// $Id: ha_sphinx.cc
3133 2012-03-01 13:47:52Z shodan
$
// $Id: ha_sphinx.cc
4507 2014-01-22 15:24:34Z deogar
$
//
//
// Copyright (c) 2001-201
2
, Andrew Aksyonoff
// Copyright (c) 2008-201
2
, Sphinx Technologies Inc
// Copyright (c) 2001-201
4
, Andrew Aksyonoff
// Copyright (c) 2008-201
4
, Sphinx Technologies Inc
// All rights reserved
//
// This program is free software; you can redistribute it and/or modify
...
...
@@ -153,7 +153,7 @@ void sphUnalignedWrite ( void * pPtr, const T & tVal )
#define SPHINXSE_MAX_ALLOC (16*1024*1024)
#define SPHINXSE_MAX_KEYWORDSTATS 4096
#define SPHINXSE_VERSION "2.
0.4
-release"
#define SPHINXSE_VERSION "2.
1.5
-release"
// FIXME? the following is cut-n-paste from sphinx.h and searchd.cpp
// cut-n-paste is somewhat simpler that adding dependencies however..
...
...
@@ -302,7 +302,11 @@ struct CSphSEShare
bool
m_bSphinxQL
;
///< is this read-only SphinxAPI table, or write-only SphinxQL table?
uint
m_iTableNameLen
;
uint
m_iUseCount
;
#if MYSQL_VERSION_ID<50610
CHARSET_INFO
*
m_pTableQueryCharset
;
#else
const
CHARSET_INFO
*
m_pTableQueryCharset
;
#endif
int
m_iTableFields
;
char
**
m_sTableField
;
...
...
@@ -431,7 +435,11 @@ struct CSphSEThreadData
bool
m_bQuery
;
char
m_sQuery
[
MAX_QUERY_LEN
];
#if MYSQL_VERSION_ID<50610
CHARSET_INFO
*
m_pQueryCharset
;
#else
const
CHARSET_INFO
*
m_pQueryCharset
;
#endif
bool
m_bReplace
;
///< are we doing an INSERT or REPLACE
...
...
@@ -521,7 +529,7 @@ private:
int
m_iWeights
;
ESphMatchMode
m_eMode
;
ESphRankMode
m_eRanker
;
c
onst
c
har
*
m_sRankExpr
;
char
*
m_sRankExpr
;
ESphSortOrder
m_eSort
;
const
char
*
m_sSortBy
;
int
m_iMaxMatches
;
...
...
@@ -552,8 +560,8 @@ private:
float
m_fGeoLatitude
;
float
m_fGeoLongitude
;
c
onst
char
*
m_sComment
;
c
onst
char
*
m_sSelect
;
c
har
*
m_sComment
;
c
har
*
m_sSelect
;
struct
Override_t
{
...
...
@@ -626,7 +634,7 @@ bool sphinx_show_status ( THD * thd );
//////////////////////////////////////////////////////////////////////////////
static
const
char
sphinx_hton_name
[]
=
"SPHINX"
;
static
const
char
sphinx_hton_comment
[]
=
"Sphinx storage engine
"
;
static
const
char
sphinx_hton_comment
[]
=
"Sphinx storage engine
"
SPHINXSE_VERSION
;
#if MYSQL_VERSION_ID<50100
handlerton
sphinx_hton
=
...
...
@@ -740,13 +748,12 @@ static int sphinx_done_func ( void * )
{
SPH_ENTER_FUNC
();
int
error
__attribute__
((
unused
))
=
0
;
if
(
sphinx_init
)
{
sphinx_init
=
0
;
#ifdef NOT_USED
if
(
sphinx_open_tables
.
records
)
error
=
1
;
#endif
sphinx_hash_free
(
&
sphinx_open_tables
);
pthread_mutex_destroy
(
&
sphinx_mutex
);
}
...
...
@@ -1002,8 +1009,8 @@ static bool ParseUrl ( CSphSEShare * share, TABLE * table, bool bCreate )
bool
bOk
=
true
;
bool
bQL
=
false
;
char
*
sScheme
=
NULL
;
char
*
sHost
=
(
char
*
)
SPHINXAPI_DEFAULT_HOST
;
char
*
sIndex
=
(
char
*
)
SPHINXAPI_DEFAULT_INDEX
;
char
*
sHost
=
SPHINXAPI_DEFAULT_HOST
;
char
*
sIndex
=
SPHINXAPI_DEFAULT_INDEX
;
int
iPort
=
SPHINXAPI_DEFAULT_PORT
;
// parse connection string, if any
...
...
@@ -1029,12 +1036,12 @@ static bool ParseUrl ( CSphSEShare * share, TABLE * table, bool bCreate )
sHost
--
;
// reuse last slash
iPort
=
0
;
if
(
!
(
sIndex
=
strrchr
(
sHost
,
':'
)
))
sIndex
=
(
char
*
)
SPHINXAPI_DEFAULT_INDEX
;
sIndex
=
SPHINXAPI_DEFAULT_INDEX
;
else
{
*
sIndex
++
=
'\0'
;
if
(
!*
sIndex
)
sIndex
=
(
char
*
)
SPHINXAPI_DEFAULT_INDEX
;
sIndex
=
SPHINXAPI_DEFAULT_INDEX
;
}
bOk
=
true
;
break
;
...
...
@@ -1056,7 +1063,7 @@ static bool ParseUrl ( CSphSEShare * share, TABLE * table, bool bCreate )
if
(
sIndex
)
*
sIndex
++
=
'\0'
;
else
sIndex
=
(
char
*
)
SPHINXAPI_DEFAULT_INDEX
;
sIndex
=
SPHINXAPI_DEFAULT_INDEX
;
iPort
=
atoi
(
sPort
);
if
(
!
iPort
)
...
...
@@ -1068,7 +1075,7 @@ static bool ParseUrl ( CSphSEShare * share, TABLE * table, bool bCreate )
if
(
sIndex
)
*
sIndex
++
=
'\0'
;
else
sIndex
=
(
char
*
)
SPHINXAPI_DEFAULT_INDEX
;
sIndex
=
SPHINXAPI_DEFAULT_INDEX
;
}
bOk
=
true
;
break
;
...
...
@@ -1371,6 +1378,11 @@ static bool myisattr ( char c )
c
==
'_'
;
}
static
bool
myismagic
(
char
c
)
{
return
c
==
'@'
;
}
bool
CSphSEQuery
::
ParseField
(
char
*
sField
)
{
...
...
@@ -1553,8 +1565,8 @@ bool CSphSEQuery::ParseField ( char * sField )
if
(
tFilter
.
m_eType
==
SPH_FILTER_RANGE
)
{
tFilter
.
m_uMinValue
=
strtoll
(
sValue
,
NULL
,
0
);
tFilter
.
m_uMaxValue
=
strtoll
(
p
,
NULL
,
0
);
tFilter
.
m_uMinValue
=
strtoll
(
sValue
,
NULL
,
1
0
);
tFilter
.
m_uMaxValue
=
strtoll
(
p
,
NULL
,
1
0
);
}
else
{
tFilter
.
m_fMinValue
=
(
float
)
atof
(
sValue
);
...
...
@@ -1576,13 +1588,13 @@ bool CSphSEQuery::ParseField ( char * sField )
tFilter
.
m_bExclude
=
(
strcmp
(
sName
,
"!filter"
)
==
0
);
// get the attr name
while
(
(
*
sValue
)
&&
!
myisattr
(
*
sValue
)
)
while
(
(
*
sValue
)
&&
!
(
myisattr
(
*
sValue
)
||
myismagic
(
*
sValue
)
)
)
sValue
++
;
if
(
!*
sValue
)
break
;
tFilter
.
m_sAttrName
=
sValue
;
while
(
(
*
sValue
)
&&
myisattr
(
*
sValue
)
)
while
(
(
*
sValue
)
&&
(
myisattr
(
*
sValue
)
||
myismagic
(
*
sValue
)
)
)
sValue
++
;
if
(
!*
sValue
)
break
;
...
...
@@ -2333,11 +2345,10 @@ int ha_sphinx::write_row ( byte * )
SPH_RET
(
ER_OUT_OF_RESOURCES
);
unsigned
int
uTimeout
=
1
;
mysql_options
(
pConn
,
MYSQL_OPT_CONNECT_TIMEOUT
,
(
const
char
*
)
&
uTimeout
);
my_bool
my_true
=
1
;
mysql_options
(
pConn
,
MYSQL_OPT_CONNECT_TIMEOUT
,
(
const
char
*
)
&
uTimeout
);
mysql_options
(
pConn
,
MYSQL_OPT_USE_THREAD_SPECIFIC_MEMORY
,
(
char
*
)
&
my_true
);
mysql_options
(
pConn
,
MYSQL_OPT_USE_THREAD_SPECIFIC_MEMORY
,
(
char
*
)
&
my_true
);
if
(
!
mysql_real_connect
(
pConn
,
m_pShare
->
m_sHost
,
"root"
,
""
,
""
,
m_pShare
->
m_iPort
,
m_pShare
->
m_sSocket
,
0
)
)
SPH_RET
(
HandleMysqlError
(
pConn
,
ER_CONNECT_TO_FOREIGN_DATA_SOURCE
)
);
...
...
@@ -2396,11 +2407,10 @@ int ha_sphinx::delete_row ( const byte * )
SPH_RET
(
ER_OUT_OF_RESOURCES
);
unsigned
int
uTimeout
=
1
;
mysql_options
(
pConn
,
MYSQL_OPT_CONNECT_TIMEOUT
,
(
const
char
*
)
&
uTimeout
);
my_bool
my_true
=
1
;
mysql_options
(
pConn
,
MYSQL_OPT_CONNECT_TIMEOUT
,
(
const
char
*
)
&
uTimeout
);
mysql_options
(
pConn
,
MYSQL_OPT_USE_THREAD_SPECIFIC_MEMORY
,
(
char
*
)
&
my_true
);
mysql_options
(
pConn
,
MYSQL_OPT_USE_THREAD_SPECIFIC_MEMORY
,
(
char
*
)
&
my_true
);
if
(
!
mysql_real_connect
(
pConn
,
m_pShare
->
m_sHost
,
"root"
,
""
,
""
,
m_pShare
->
m_iPort
,
m_pShare
->
m_sSocket
,
0
)
)
SPH_RET
(
HandleMysqlError
(
pConn
,
ER_CONNECT_TO_FOREIGN_DATA_SOURCE
)
);
...
...
@@ -2676,12 +2686,16 @@ bool ha_sphinx::UnpackStats ( CSphSEStats * pStats )
/// condition pushdown implementation, to properly intercept WHERE clauses on my columns
#if MYSQL_VERSION_ID<50610
const
COND
*
ha_sphinx
::
cond_push
(
const
COND
*
cond
)
#else
const
Item
*
ha_sphinx
::
cond_push
(
const
Item
*
cond
)
#endif
{
// catch the simplest case: query_column="some text"
for
(
;;
)
{
if
(
cond
->
type
()
!=
COND
::
FUNC_ITEM
)
if
(
cond
->
type
()
!=
Item
::
FUNC_ITEM
)
break
;
Item_func
*
condf
=
(
Item_func
*
)
cond
;
...
...
@@ -2697,7 +2711,7 @@ const COND * ha_sphinx::cond_push ( const COND * cond )
if
(
!
m_pShare
->
m_bSphinxQL
)
{
// on non-QL tables, intercept query=value condition for SELECT
if
(
!
(
args
[
0
]
->
type
()
==
COND
::
FIELD_ITEM
&&
args
[
1
]
->
type
()
==
COND
::
STRING_ITEM
))
if
(
!
(
args
[
0
]
->
type
()
==
Item
::
FIELD_ITEM
&&
args
[
1
]
->
type
()
==
Item
::
STRING_ITEM
))
break
;
Item_field
*
pField
=
(
Item_field
*
)
args
[
0
];
...
...
@@ -2713,7 +2727,7 @@ const COND * ha_sphinx::cond_push ( const COND * cond )
}
else
{
if
(
!
(
args
[
0
]
->
type
()
==
COND
::
FIELD_ITEM
&&
args
[
1
]
->
type
()
==
COND
::
INT_ITEM
))
if
(
!
(
args
[
0
]
->
type
()
==
Item
::
FIELD_ITEM
&&
args
[
1
]
->
type
()
==
Item
::
INT_ITEM
))
break
;
// on QL tables, intercept id=value condition for DELETE
...
...
@@ -3302,6 +3316,9 @@ ha_rows ha_sphinx::records_in_range ( uint, key_range *, key_range * )
SPH_RET
(
3
);
// low number to force index usage
}
#if MYSQL_VERSION_ID < 50610
#define user_defined_key_parts key_parts
#endif
// create() is called to create a database. The variable name will have the name
// of the table. When create() is called you do not need to worry about opening
...
...
@@ -3370,7 +3387,7 @@ int ha_sphinx::create ( const char * name, TABLE * table, HA_CREATE_INFO * )
// check index
if
(
table
->
s
->
keys
!=
1
||
table
->
key_info
[
0
].
user_defined_key_parts
!=
1
||
table
->
key_info
[
0
].
user_defined_key_parts
!=
1
||
strcasecmp
(
table
->
key_info
[
0
].
key_part
[
0
].
field
->
field_name
,
table
->
field
[
2
]
->
field_name
)
)
{
my_snprintf
(
sError
,
sizeof
(
sError
),
"%s: there must be an index on '%s' column"
,
...
...
@@ -3618,5 +3635,5 @@ maria_declare_plugin_end;
#endif // >50100
//
// $Id: ha_sphinx.cc
3133 2012-03-01 13:47:52Z shodan
$
// $Id: ha_sphinx.cc
4507 2014-01-22 15:24:34Z deogar
$
//
storage/sphinx/ha_sphinx.h
View file @
65121806
//
// $Id: ha_sphinx.h
2921 2011-08-21 21:35:02Z tomat
$
// $Id: ha_sphinx.h
3866 2013-05-22 11:54:20Z kevg
$
//
#ifdef USE_PRAGMA_INTERFACE
...
...
@@ -128,7 +128,11 @@ public:
THR_LOCK_DATA
**
store_lock
(
THD
*
thd
,
THR_LOCK_DATA
**
to
,
enum
thr_lock_type
lock_type
);
public:
#if MYSQL_VERSION_ID<50610
virtual
const
COND
*
cond_push
(
const
COND
*
cond
);
#else
virtual
const
Item
*
cond_push
(
const
Item
*
cond
);
#endif
virtual
void
cond_pop
();
private:
...
...
@@ -167,5 +171,5 @@ int sphinx_showfunc_word_count ( THD *, SHOW_VAR *, char * );
int
sphinx_showfunc_words
(
THD
*
,
SHOW_VAR
*
,
char
*
);
//
// $Id: ha_sphinx.h
2921 2011-08-21 21:35:02Z tomat
$
// $Id: ha_sphinx.h
3866 2013-05-22 11:54:20Z kevg
$
//
storage/sphinx/make-patch.sh
100644 → 100755
View file @
65121806
File mode changed from 100644 to 100755
storage/sphinx/snippets_udf.cc
View file @
65121806
//
// $Id: snippets_udf.cc
3508 2012-11-05 11:48:48Z kevg
$
// $Id: snippets_udf.cc
4505 2014-01-22 15:16:21Z deogar
$
//
//
// Copyright (c) 2001-201
2
, Andrew Aksyonoff
// Copyright (c) 2008-201
2
, Sphinx Technologies Inc
// Copyright (c) 2001-201
4
, Andrew Aksyonoff
// Copyright (c) 2008-201
4
, Sphinx Technologies Inc
// All rights reserved
//
// This program is free software; you can redistribute it and/or modify
...
...
@@ -180,7 +180,7 @@ enum
#define SPHINXSE_DEFAULT_SCHEME "sphinx"
#define SPHINXSE_DEFAULT_HOST "127.0.0.1"
#define SPHINXSE_DEFAULT_PORT 9312
#define SPHINXSE_DEFAULT_INDEX
(char*)
"*"
#define SPHINXSE_DEFAULT_INDEX "*"
class
CSphBuffer
{
...
...
@@ -244,7 +244,7 @@ struct CSphUrl
char
*
m_sBuffer
;
char
*
m_sFormatted
;
c
onst
c
har
*
m_sScheme
;
char
*
m_sScheme
;
char
*
m_sHost
;
char
*
m_sIndex
;
...
...
@@ -254,7 +254,7 @@ struct CSphUrl
:
m_sBuffer
(
NULL
)
,
m_sFormatted
(
NULL
)
,
m_sScheme
(
SPHINXSE_DEFAULT_SCHEME
)
,
m_sHost
(
(
char
*
)
SPHINXSE_DEFAULT_HOST
)
,
m_sHost
(
SPHINXSE_DEFAULT_HOST
)
,
m_sIndex
(
SPHINXSE_DEFAULT_INDEX
)
,
m_iPort
(
SPHINXSE_DEFAULT_PORT
)
{}
...
...
@@ -311,12 +311,12 @@ bool CSphUrl::Parse ( const char * sUrl, int iLen )
// unix-domain socket
m_iPort
=
0
;
if
(
!
(
m_sIndex
=
strrchr
(
m_sHost
,
':'
)
))
m_sIndex
=
const_cast
<
char
*>
(
SPHINXSE_DEFAULT_INDEX
)
;
m_sIndex
=
SPHINXSE_DEFAULT_INDEX
;
else
{
*
m_sIndex
++
=
'\0'
;
if
(
!*
m_sIndex
)
m_sIndex
=
const_cast
<
char
*>
(
SPHINXSE_DEFAULT_INDEX
)
;
m_sIndex
=
SPHINXSE_DEFAULT_INDEX
;
}
bOk
=
true
;
break
;
...
...
@@ -336,7 +336,7 @@ bool CSphUrl::Parse ( const char * sUrl, int iLen )
if
(
m_sIndex
)
*
m_sIndex
++
=
'\0'
;
else
m_sIndex
=
const_cast
<
char
*>
(
SPHINXSE_DEFAULT_INDEX
)
;
m_sIndex
=
SPHINXSE_DEFAULT_INDEX
;
m_iPort
=
atoi
(
sPort
);
if
(
!
m_iPort
)
...
...
@@ -348,7 +348,7 @@ bool CSphUrl::Parse ( const char * sUrl, int iLen )
if
(
m_sIndex
)
*
m_sIndex
++
=
'\0'
;
else
m_sIndex
=
const_cast
<
char
*>
(
SPHINXSE_DEFAULT_INDEX
)
;
m_sIndex
=
SPHINXSE_DEFAULT_INDEX
;
}
bOk
=
true
;
...
...
@@ -446,7 +446,7 @@ int CSphUrl::Connect()
uint
uServerVersion
;
uint
uClientVersion
=
htonl
(
SPHINX_SEARCHD_PROTO
);
int
iSocket
=
-
1
;
c
onst
c
har
*
pError
=
NULL
;
char
*
pError
=
NULL
;
do
{
iSocket
=
socket
(
iDomain
,
SOCK_STREAM
,
0
);
...
...
@@ -567,6 +567,7 @@ CSphResponse::Read ( int iSocket, int iClientVersion )
#else
#define DLLEXPORT
#endif
extern
"C"
{
DLLEXPORT
my_bool
sphinx_snippets_init
(
UDF_INIT
*
pUDF
,
UDF_ARGS
*
pArgs
,
char
*
sMessage
);
...
...
@@ -640,7 +641,7 @@ struct CSphSnippets
}
#define STRING CHECK_TYPE(STRING_RESULT)
#define INT CHECK_TYPE(INT_RESULT); int iValue =
(int)
*(long long *)pArgs->args[i]
#define INT CHECK_TYPE(INT_RESULT); int iValue = *(long long *)pArgs->args[i]
my_bool
sphinx_snippets_init
(
UDF_INIT
*
pUDF
,
UDF_ARGS
*
pArgs
,
char
*
sMessage
)
{
...
...
@@ -820,5 +821,5 @@ void sphinx_snippets_deinit ( UDF_INIT * pUDF )
}
//
// $Id: snippets_udf.cc
3508 2012-11-05 11:48:48Z kevg
$
// $Id: snippets_udf.cc
4505 2014-01-22 15:16:21Z deogar
$
//
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment