Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
varnish-cache
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
varnishcache
varnish-cache
Commits
c122a396
Commit
c122a396
authored
May 23, 2017
by
Poul-Henning Kamp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Also move VSC::LCK to The New World Order
parent
a32fb96c
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
101 additions
and
38 deletions
+101
-38
Makefile.am
bin/varnishd/Makefile.am
+13
-3
cache.h
bin/varnishd/cache/cache.h
+4
-4
cache_lck.c
bin/varnishd/cache/cache_lck.c
+7
-6
cache_shmlog.c
bin/varnishd/cache/cache_shmlog.c
+24
-8
common.h
bin/varnishd/common/common.h
+1
-1
hash_classic.c
bin/varnishd/hash/hash_classic.c
+1
-1
hash_simple_list.c
bin/varnishd/hash/hash_simple_list.c
+1
-1
lck.vsc
bin/varnishd/lck.vsc
+30
-0
main.vsc
bin/varnishd/main.vsc
+1
-1
storage_file.c
bin/varnishd/storage/storage_file.c
+1
-1
storage_malloc.c
bin/varnishd/storage/storage_malloc.c
+1
-1
storage_persistent.c
bin/varnishd/storage/storage_persistent.c
+1
-1
vsc_int.h
include/vapi/vsc_int.h
+1
-1
vsctool.py
lib/libvcc/vsctool.py
+15
-9
No files found.
bin/varnishd/Makefile.am
View file @
c122a396
...
@@ -107,8 +107,7 @@ varnishd_SOURCES = \
...
@@ -107,8 +107,7 @@ varnishd_SOURCES = \
waiter/cache_waiter_epoll.c
\
waiter/cache_waiter_epoll.c
\
waiter/cache_waiter_kqueue.c
\
waiter/cache_waiter_kqueue.c
\
waiter/cache_waiter_poll.c
\
waiter/cache_waiter_poll.c
\
waiter/cache_waiter_ports.c
\
waiter/cache_waiter_ports.c
VSC_main.c
nodist_varnishd_SOURCES
=
\
nodist_varnishd_SOURCES
=
\
builtin_vcl.c
builtin_vcl.c
...
@@ -219,10 +218,21 @@ DISTCLEANFILES += vhp_hufdec.h
...
@@ -219,10 +218,21 @@ DISTCLEANFILES += vhp_hufdec.h
#######################################################################
#######################################################################
VSC_main.c VSC_main.h
:
$(srcdir)/main.vsc $(top_builddir)/lib/libvcc/vsctool.py
VSC_main.c VSC_main.h
:
$(srcdir)/main.vsc $(top_builddir)/lib/libvcc/vsctool.py
$(PYTHON)
$(top_
build
dir)
/lib/libvcc/vsctool.py
$(srcdir)
/main.vsc
$(PYTHON)
$(top_
src
dir)
/lib/libvcc/vsctool.py
$(srcdir)
/main.vsc
$(varnishd_OBJECTS)
:
VSC_main.h
$(varnishd_OBJECTS)
:
VSC_main.h
EXTRA_DIST
+=
main.vsc
EXTRA_DIST
+=
main.vsc
DISTCLEANFILES
+=
VSC_main.c VSC_main.h
DISTCLEANFILES
+=
VSC_main.c VSC_main.h
nodist_varnishd_SOURCES
+=
VSC_main.c
#######################################################################
VSC_lck.c VSC_lck.h
:
$(srcdir)/lck.vsc $(top_builddir)/lib/libvcc/vsctool.py
$(PYTHON)
$(top_srcdir)
/lib/libvcc/vsctool.py
$(srcdir)
/lck.vsc
$(varnishd_OBJECTS)
:
VSC_lck.h
EXTRA_DIST
+=
lck.vsc
DISTCLEANFILES
+=
VSC_lck.c VSC_lck.h
nodist_varnishd_SOURCES
+=
VSC_lck.c
bin/varnishd/cache/cache.h
View file @
c122a396
...
@@ -95,7 +95,7 @@ enum {
...
@@ -95,7 +95,7 @@ enum {
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
struct
VSC_
C_
lck
;
struct
VSC_lck
;
struct
ban
;
struct
ban
;
struct
ban_proto
;
struct
ban_proto
;
struct
backend
;
struct
backend
;
...
@@ -828,7 +828,7 @@ extern pthread_key_t witness_key;
...
@@ -828,7 +828,7 @@ extern pthread_key_t witness_key;
void
Lck__Lock
(
struct
lock
*
lck
,
const
char
*
p
,
int
l
);
void
Lck__Lock
(
struct
lock
*
lck
,
const
char
*
p
,
int
l
);
void
Lck__Unlock
(
struct
lock
*
lck
,
const
char
*
p
,
int
l
);
void
Lck__Unlock
(
struct
lock
*
lck
,
const
char
*
p
,
int
l
);
int
Lck__Trylock
(
struct
lock
*
lck
,
const
char
*
p
,
int
l
);
int
Lck__Trylock
(
struct
lock
*
lck
,
const
char
*
p
,
int
l
);
void
Lck__New
(
struct
lock
*
lck
,
struct
VSC_
C_
lck
*
,
const
char
*
);
void
Lck__New
(
struct
lock
*
lck
,
struct
VSC_lck
*
,
const
char
*
);
int
Lck__Held
(
const
struct
lock
*
lck
);
int
Lck__Held
(
const
struct
lock
*
lck
);
int
Lck__Owned
(
const
struct
lock
*
lck
);
int
Lck__Owned
(
const
struct
lock
*
lck
);
...
@@ -846,9 +846,9 @@ int Lck_CondWait(pthread_cond_t *cond, struct lock *lck, double);
...
@@ -846,9 +846,9 @@ int Lck_CondWait(pthread_cond_t *cond, struct lock *lck, double);
assert(Lck__Owned(a)); \
assert(Lck__Owned(a)); \
} while (0)
} while (0)
struct
VSC_
C_
lck
*
Lck_CreateClass
(
const
char
*
name
);
struct
VSC_lck
*
Lck_CreateClass
(
const
char
*
name
);
#define LOCK(nam) extern struct VSC_
C_
lck *lck_##nam;
#define LOCK(nam) extern struct VSC_lck *lck_##nam;
#include "tbl/locks.h"
#include "tbl/locks.h"
/* cache_mempool.c */
/* cache_mempool.c */
...
...
bin/varnishd/cache/cache_lck.c
View file @
c122a396
...
@@ -41,6 +41,8 @@
...
@@ -41,6 +41,8 @@
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include "VSC_lck.h"
struct
ilck
{
struct
ilck
{
unsigned
magic
;
unsigned
magic
;
#define ILCK_MAGIC 0x7b86c8a5
#define ILCK_MAGIC 0x7b86c8a5
...
@@ -48,7 +50,7 @@ struct ilck {
...
@@ -48,7 +50,7 @@ struct ilck {
pthread_mutex_t
mtx
;
pthread_mutex_t
mtx
;
pthread_t
owner
;
pthread_t
owner
;
const
char
*
w
;
const
char
*
w
;
struct
VSC_
C_lck
*
stat
;
struct
VSC_
lck
*
stat
;
};
};
static
pthread_mutexattr_t
attr
;
static
pthread_mutexattr_t
attr
;
...
@@ -214,7 +216,7 @@ Lck_CondWait(pthread_cond_t *cond, struct lock *lck, double when)
...
@@ -214,7 +216,7 @@ Lck_CondWait(pthread_cond_t *cond, struct lock *lck, double when)
}
}
void
void
Lck__New
(
struct
lock
*
lck
,
struct
VSC_
C_
lck
*
st
,
const
char
*
w
)
Lck__New
(
struct
lock
*
lck
,
struct
VSC_lck
*
st
,
const
char
*
w
)
{
{
struct
ilck
*
ilck
;
struct
ilck
*
ilck
;
...
@@ -242,14 +244,13 @@ Lck_Delete(struct lock *lck)
...
@@ -242,14 +244,13 @@ Lck_Delete(struct lock *lck)
FREE_OBJ
(
ilck
);
FREE_OBJ
(
ilck
);
}
}
struct
VSC_
C_
lck
*
struct
VSC_lck
*
Lck_CreateClass
(
const
char
*
name
)
Lck_CreateClass
(
const
char
*
name
)
{
{
return
(
VSM_Alloc
(
sizeof
(
struct
VSC_C_lck
),
return
(
VSC_lck_New
(
name
));
VSC_CLASS
,
VSC_type_lck
,
name
));
}
}
#define LOCK(nam) struct VSC_
C_
lck *lck_##nam;
#define LOCK(nam) struct VSC_lck *lck_##nam;
#include "tbl/locks.h"
#include "tbl/locks.h"
void
void
...
...
bin/varnishd/cache/cache_shmlog.c
View file @
c122a396
...
@@ -37,6 +37,8 @@
...
@@ -37,6 +37,8 @@
#include "common/heritage.h"
#include "common/heritage.h"
#include "vend.h"
#include "vgz.h"
#include "vsl_priv.h"
#include "vsl_priv.h"
#include "vmb.h"
#include "vmb.h"
#include "vtim.h"
#include "vtim.h"
...
@@ -471,16 +473,32 @@ VSL_End(struct vsl_log *vsl)
...
@@ -471,16 +473,32 @@ VSL_End(struct vsl_log *vsl)
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
void
*
void
*
VSC_Alloc
(
const
char
*
nm
,
size_t
sj
,
const
unsigned
char
*
zj
,
size_t
szj
,
VSC_Alloc
(
const
char
*
nm
,
size_t
sd
,
size_t
sj
,
const
unsigned
char
*
zj
,
size_t
szj
,
const
char
*
fmt
,
va_list
va
)
const
char
*
fmt
,
va_list
va
)
{
{
char
*
p
;
z_stream
vz
;
(
void
)
nm
;
(
void
)
nm
;
(
void
)
zj
;
(
void
)
szj
;
(
void
)
sj
;
(
void
)
fmt
;
(
void
)
fmt
;
(
void
)
va
;
(
void
)
va
;
return
(
0
);
p
=
VSM_Alloc
(
sd
+
sj
,
VSC_CLASS
,
nm
,
fmt
);
AN
(
p
);
memset
(
p
,
0
,
sd
);
vbe64enc
(
p
,
sd
);
// fills .zero
memset
(
&
vz
,
0
,
sizeof
vz
);
assert
(
Z_OK
==
inflateInit2
(
&
vz
,
31
));
vz
.
next_in
=
TRUST_ME
(
zj
);
vz
.
avail_in
=
szj
;
vz
.
next_out
=
(
void
*
)(
p
+
sd
);
vz
.
avail_out
=
sj
;
assert
(
Z_STREAM_END
==
inflate
(
&
vz
,
Z_FINISH
));
assert
(
Z_OK
==
inflateEnd
(
&
vz
));
return
(
p
);
}
}
void
void
...
@@ -540,10 +558,8 @@ VSM_Init(void)
...
@@ -540,10 +558,8 @@ VSM_Init(void)
VWMB
();
VWMB
();
memcpy
(
vsl_head
->
marker
,
VSL_HEAD_MARKER
,
sizeof
vsl_head
->
marker
);
memcpy
(
vsl_head
->
marker
,
VSL_HEAD_MARKER
,
sizeof
vsl_head
->
marker
);
VSC_C_main
=
VSM_Alloc
(
sizeof
*
VSC_C_main
,
VSC_C_main
=
VSC_main_New
(
""
);
VSC_CLASS
,
VSC_type_main
,
""
);
AN
(
VSC_C_main
);
AN
(
VSC_C_main
);
memset
(
VSC_C_main
,
0
,
sizeof
*
VSC_C_main
);
AZ
(
pthread_create
(
&
tp
,
NULL
,
vsm_cleaner
,
NULL
));
AZ
(
pthread_create
(
&
tp
,
NULL
,
vsm_cleaner
,
NULL
));
}
}
...
...
bin/varnishd/common/common.h
View file @
c122a396
...
@@ -91,7 +91,7 @@ void VSM_common_copy(struct vsm_sc *to, const struct vsm_sc *from);
...
@@ -91,7 +91,7 @@ void VSM_common_copy(struct vsm_sc *to, const struct vsm_sc *from);
void
VSM_common_cleaner
(
struct
vsm_sc
*
sc
,
struct
VSC_C_main
*
stats
);
void
VSM_common_cleaner
(
struct
vsm_sc
*
sc
,
struct
VSC_C_main
*
stats
);
void
VSM_common_ageupdate
(
const
struct
vsm_sc
*
sc
);
void
VSM_common_ageupdate
(
const
struct
vsm_sc
*
sc
);
void
*
VSC_Alloc
(
const
char
*
,
size_t
,
const
unsigned
char
*
,
size_t
,
void
*
VSC_Alloc
(
const
char
*
,
size_t
,
size_t
,
const
unsigned
char
*
,
size_t
,
const
char
*
,
va_list
);
const
char
*
,
va_list
);
void
VSC_Destroy
(
const
char
*
,
void
*
);
void
VSC_Destroy
(
const
char
*
,
void
*
);
...
...
bin/varnishd/hash/hash_classic.c
View file @
c122a396
...
@@ -38,7 +38,7 @@
...
@@ -38,7 +38,7 @@
#include "hash/hash_slinger.h"
#include "hash/hash_slinger.h"
static
struct
VSC_
C_
lck
*
lck_hcl
;
static
struct
VSC_lck
*
lck_hcl
;
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
...
...
bin/varnishd/hash/hash_simple_list.c
View file @
c122a396
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
#include "hash/hash_slinger.h"
#include "hash/hash_slinger.h"
static
struct
VSC_
C_
lck
*
lck_hsl
;
static
struct
VSC_lck
*
lck_hsl
;
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
...
...
bin/varnishd/lck.vsc
0 → 100644
View file @
c122a396
..
This is *NOT* a RST file but the syntax has been chosen so
that it may become an RST file at some later date.
XXX: For now this file must be kept in 100% agreement with
XXX: include/tbl/vsc_fields.h
.. varnish_vsc_begin:: lck
:oneliner: LOCK COUNTERS (LCK.*)
.. varnish_vsc:: creat
:type: counter
:level: debug
:oneliner: Created locks
.. varnish_vsc:: destroy
:type: counter
:level: debug
:oneliner: Destroyed locks
.. varnish_vsc:: locks
:type: counter
:level: debug
:oneliner: Lock Operations
.. varnish_vsc_end:: lck
bin/varnishd/main.vsc
View file @
c122a396
...
@@ -753,4 +753,4 @@ to communicate with tools like varnishstat, varnishlog etc. If this
...
@@ -753,4 +753,4 @@ to communicate with tools like varnishstat, varnishlog etc. If this
counter is not zero, consider increasing the runtime variable
counter is not zero, consider increasing the runtime variable
vsm_space.
vsm_space.
.. varnish_vsc_end::
MAIN
.. varnish_vsc_end::
main
bin/varnishd/storage/storage_file.c
View file @
c122a396
...
@@ -64,7 +64,7 @@
...
@@ -64,7 +64,7 @@
*/
*/
#define NBUCKET (128 / 4 + 1)
#define NBUCKET (128 / 4 + 1)
static
struct
VSC_
C_
lck
*
lck_smf
;
static
struct
VSC_lck
*
lck_smf
;
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
...
...
bin/varnishd/storage/storage_malloc.c
View file @
c122a396
...
@@ -59,7 +59,7 @@ struct sma {
...
@@ -59,7 +59,7 @@ struct sma {
struct
sma_sc
*
sc
;
struct
sma_sc
*
sc
;
};
};
static
struct
VSC_
C_
lck
*
lck_sma
;
static
struct
VSC_lck
*
lck_sma
;
static
struct
storage
*
__match_proto__
(
sml_alloc_f
)
static
struct
storage
*
__match_proto__
(
sml_alloc_f
)
sma_alloc
(
const
struct
stevedore
*
st
,
size_t
size
)
sma_alloc
(
const
struct
stevedore
*
st
,
size_t
size
)
...
...
bin/varnishd/storage/storage_persistent.c
View file @
c122a396
...
@@ -55,7 +55,7 @@
...
@@ -55,7 +55,7 @@
static
struct
obj_methods
smp_oc_realmethods
;
static
struct
obj_methods
smp_oc_realmethods
;
static
struct
VSC_
C_
lck
*
lck_smp
;
static
struct
VSC_lck
*
lck_smp
;
static
void
smp_init
(
void
);
static
void
smp_init
(
void
);
...
...
include/vapi/vsc_int.h
View file @
c122a396
...
@@ -43,7 +43,7 @@ enum VSC_level_e {
...
@@ -43,7 +43,7 @@ enum VSC_level_e {
#include "tbl/vsc_types.h"
#include "tbl/vsc_types.h"
/* Define the vsc type structs */
/* Define the vsc type structs */
#define VSC_DO(u,l,t,h) struct VSC_C_##l {
#define VSC_DO(u,l,t,h) struct VSC_C_##l {
uint64_t zero;
#define VSC_F(n,t,l,s,f,v,d,e) t n;
#define VSC_F(n,t,l,s,f,v,d,e) t n;
#define VSC_DONE(u,l,t) };
#define VSC_DONE(u,l,t) };
#include "tbl/vsc_all.h"
#include "tbl/vsc_all.h"
lib/libvcc/vsctool.py
View file @
c122a396
...
@@ -49,8 +49,8 @@ def genhdr(fo, name):
...
@@ -49,8 +49,8 @@ def genhdr(fo, name):
fo
.
write
(
' * NB: This file is machine generated, DO NOT EDIT!
\n
'
)
fo
.
write
(
' * NB: This file is machine generated, DO NOT EDIT!
\n
'
)
fo
.
write
(
' *
\n
'
)
fo
.
write
(
' *
\n
'
)
fo
.
write
(
' * Edit
%
s.vsc run lib/libvcc/vsctool.py instead.
\n
'
%
name
)
fo
.
write
(
' * Edit
%
s.vsc run lib/libvcc/vsctool.py instead.
\n
'
%
name
)
fo
.
write
(
' */
\n
'
)
fo
.
write
(
' */
\n
'
)
fo
.
write
(
'
\n
'
)
fo
.
write
(
'
\n
'
)
#######################################################################
#######################################################################
...
@@ -90,11 +90,11 @@ class vscset(object):
...
@@ -90,11 +90,11 @@ class vscset(object):
ed
[
"1line"
]
=
i
.
param
[
"oneliner"
]
.
strip
()
ed
[
"1line"
]
=
i
.
param
[
"oneliner"
]
.
strip
()
ed
[
"docs"
]
=
i
.
getdoc
()
ed
[
"docs"
]
=
i
.
getdoc
()
s
=
json
.
dumps
(
dd
,
separators
=
(
","
,
":"
))
s
=
json
.
dumps
(
dd
,
separators
=
(
","
,
":"
))
fo
.
write
(
"
\n
static const size_t
%
s_jsonlen =
%
dL;
\n
"
%
fo
.
write
(
"
\n
static const size_t
vsc_
%
s_jsonlen =
%
dL;
\n
"
%
(
self
.
name
,
len
(
s
)))
(
self
.
name
,
len
(
s
)))
z
=
gzip_str
(
s
)
z
=
gzip_str
(
s
)
fo
.
write
(
"
\n
static const unsigned char"
);
fo
.
write
(
"
\n
static const unsigned char"
);
fo
.
write
(
"
%
s_zjson[
%
d] = {
\n
"
%
(
self
.
name
,
len
(
z
)))
fo
.
write
(
"
vsc_
%
s_zjson[
%
d] = {
\n
"
%
(
self
.
name
,
len
(
z
)))
bz
=
bytearray
(
z
)
bz
=
bytearray
(
z
)
t
=
"
\t
"
t
=
"
\t
"
for
i
in
bz
:
for
i
in
bz
:
...
@@ -116,6 +116,7 @@ class vscset(object):
...
@@ -116,6 +116,7 @@ class vscset(object):
fo
=
open
(
fon
,
"w"
)
fo
=
open
(
fon
,
"w"
)
genhdr
(
fo
,
self
.
name
)
genhdr
(
fo
,
self
.
name
)
fo
.
write
(
self
.
struct
+
" {
\n
"
)
fo
.
write
(
self
.
struct
+
" {
\n
"
)
fo
.
write
(
"
\t
uint64_t
\t
zero;
\n
"
)
for
i
in
self
.
mbrs
:
for
i
in
self
.
mbrs
:
fo
.
write
(
"
\t
uint64_t
\t
%
s;
\n
"
%
i
.
arg
)
fo
.
write
(
"
\t
uint64_t
\t
%
s;
\n
"
%
i
.
arg
)
fo
.
write
(
"};
\n
"
)
fo
.
write
(
"};
\n
"
)
...
@@ -135,6 +136,10 @@ class vscset(object):
...
@@ -135,6 +136,10 @@ class vscset(object):
fo
.
write
(
'#include <stdint.h>
\n
'
)
fo
.
write
(
'#include <stdint.h>
\n
'
)
fo
.
write
(
'#include "common/common.h"
\n
'
)
fo
.
write
(
'#include "common/common.h"
\n
'
)
fo
.
write
(
'#include "VSC_
%
s.h"
\n
'
%
self
.
name
)
fo
.
write
(
'#include "VSC_
%
s.h"
\n
'
%
self
.
name
)
fo
.
write
(
"
\n
"
)
fo
.
write
(
'static const char vsc_
%
s_name[] = "
%
s";
\n
'
%
(
self
.
name
,
self
.
name
.
upper
()))
self
.
emit_json
(
fo
)
self
.
emit_json
(
fo
)
fo
.
write
(
"
\n
"
)
fo
.
write
(
"
\n
"
)
fo
.
write
(
self
.
struct
+
"*
\n
"
);
fo
.
write
(
self
.
struct
+
"*
\n
"
);
...
@@ -146,10 +151,11 @@ class vscset(object):
...
@@ -146,10 +151,11 @@ class vscset(object):
fo
.
write
(
"
\n
"
)
fo
.
write
(
"
\n
"
)
fo
.
write
(
"
\t
va_start(ap, fmt);
\n
"
)
fo
.
write
(
"
\t
va_start(ap, fmt);
\n
"
)
fo
.
write
(
"
\t
retval = VSC_Alloc"
)
fo
.
write
(
"
\t
retval = VSC_Alloc"
)
fo
.
write
(
'("'
+
self
.
name
+
'", '
)
fo
.
write
(
"(vsc_"
+
self
.
name
+
"_name, "
)
fo
.
write
(
self
.
name
+
"_jsonlen, "
)
fo
.
write
(
"sizeof("
+
self
.
struct
+
"),
\n\t
"
)
fo
.
write
(
self
.
name
+
"_zjson, "
)
fo
.
write
(
"vsc_"
+
self
.
name
+
"_jsonlen, "
)
fo
.
write
(
"sizeof "
+
self
.
name
+
"_zjson,
\n
"
)
fo
.
write
(
"vsc_"
+
self
.
name
+
"_zjson, "
)
fo
.
write
(
"sizeof vsc_"
+
self
.
name
+
"_zjson,
\n
"
)
fo
.
write
(
"
\t
fmt, ap);
\n
"
)
fo
.
write
(
"
\t
fmt, ap);
\n
"
)
fo
.
write
(
"
\t
va_end(ap);
\n
"
)
fo
.
write
(
"
\t
va_end(ap);
\n
"
)
fo
.
write
(
"
\t
return(retval);
\n
"
)
fo
.
write
(
"
\t
return(retval);
\n
"
)
...
@@ -309,6 +315,6 @@ if __name__ == "__main__":
...
@@ -309,6 +315,6 @@ if __name__ == "__main__":
exit
(
2
)
exit
(
2
)
vf
=
vsc_file
(
args
[
0
])
vf
=
vsc_file
(
args
[
0
])
vf
.
emit_rst
(
"_.rst"
)
#
vf.emit_rst("_.rst")
vf
.
emit_h
()
vf
.
emit_h
()
vf
.
emit_c
()
vf
.
emit_c
()
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