Skip to content

Commit c9ec40d

Browse files
committed
frontend: repost 'STM' blog
1 parent 2f9b25b commit c9ec40d

16 files changed

+483
-19
lines changed

frontend/app/app.routing.ts

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { versions_tip_Component } from './doc/tip/versions.component';
2424
import { BlogComponent } from './blog/blog.component';
2525
import { AnnouncingEtcdV31Component } from './blog/2016/announcing-etcd-v3.1.component';
2626
import { AnnouncingEtcdWebsiteComponent } from './blog/2016/announcing-etcd-website.component';
27+
import { STMComponent } from './blog/2016/stm.component';
2728

2829
/*
2930
/play
@@ -67,6 +68,7 @@ const appRoutes: Routes = [
6768
children: [
6869
{ path: 'announcing-etcd-v31', component: AnnouncingEtcdV31Component },
6970
{ path: 'announcing-etcd-website', component: AnnouncingEtcdWebsiteComponent },
71+
{ path: 'etcd-stm', component: STMComponent },
7072
],
7173
}
7274
],
@@ -102,6 +104,7 @@ export const routedComponents = [
102104
BlogComponent,
103105
AnnouncingEtcdV31Component,
104106
AnnouncingEtcdWebsiteComponent,
107+
STMComponent,
105108

106109
PlayComponent,
107110

frontend/app/blog/2016/announcing-etcd-v3.1.component.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
<div class="blog-group">
2121
<router-outlet></router-outlet>
2222
<h2 class="blog-title">Announcing etcd v3.1</h2>
23-
<time class="blog-date" datetime="2016-10-01 00:00">1 October 2016</time>
24-
<p class="blog-author">By etcd team</p>
23+
<time class="blog-date" datetime="2016-10-15 00:00">15 October 2016</time>
24+
<p class="blog-author">By <a href="https://github.com/coreos/etcd" target="_blank" class="blog-author-link">etcd team</a></p>
2525

2626
<br>
2727
<article class="blog-contents">

frontend/app/blog/2016/announcing-etcd-website.component.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<router-outlet></router-outlet>
2222
<h2 class="blog-title">Announcing etcd website</h2>
2323
<time class="blog-date" datetime="2016-10-01 00:00">1 October 2016</time>
24-
<p class="blog-author">By etcd team</p>
24+
<p class="blog-author">By <a href="https://github.com/coreos/etcd" target="_blank" class="blog-author-link">etcd team</a></p>
2525

2626
<br>
2727
<article class="blog-contents">
10.8 KB
Loading
14.4 KB
Loading
15.8 KB
Loading
6.22 KB
Loading
7.76 KB
Loading

frontend/app/blog/2016/stm.component.html

+242
Large diffs are not rendered by default.
+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import { Component } from '@angular/core';
2+
import { BlogComponent } from '../blog.component';
3+
4+
@Component({
5+
selector: 'stm',
6+
templateUrl: 'stm.component.html',
7+
})
8+
export class STMComponent extends BlogComponent {
9+
constructor() {
10+
super();
11+
}
12+
13+
getCode1() {
14+
return `import (
15+
"fmt"
16+
"encoding/binary"
17+
v3 "github.com/coreos/etcd/clientv3"
18+
)
19+
20+
func toUInt64(v []byte) uint64 { x, _ := binary.UVarint(v); return x }
21+
func fromUInt64(v uint64) []byte {
22+
b := make([]byte, binary.MaxVarintLen64);
23+
return b[:binary.PutUvarint(b, v)]
24+
}
25+
26+
func nosyncXfer(etcd *v3.Client, from, to string, amount uint) (err error) {
27+
var fromKV, toKV *v3.GetResponse
28+
if fromKV, err = b.etcd.Get(context.TODO(), from); err != nil {
29+
return err
30+
}
31+
if toKV, err = b.etcd.Get(context.TODO(), to); err != nil {
32+
return err
33+
}
34+
fromV, toV := toUInt64(fromKV.Value), toUint64(toKV.Value)
35+
if fromV < amount {
36+
return fmt.Errorf("insufficient value")
37+
}
38+
if _, err = b.etcd.Put(context.TODO(), to, fromUInt64(toV + amount)); err != nil {
39+
return err
40+
}
41+
_, err = b.etcd.Put(context.TODO(), from, fromUInt64(fromV - amount))
42+
return err
43+
}
44+
`;
45+
}
46+
47+
getCode2() {
48+
return `func txnXfer(etcd *v3.Client, from, to string, amount uint) (error) {
49+
for {
50+
if ok, err := doTxnXfer(etcd, from, to amount); err != nil {
51+
return err
52+
} else if ok {
53+
return nil
54+
}
55+
}
56+
}
57+
58+
func doTxnXfer(etcd *v3.Client, from, to string, amount uint) (bool, error) {
59+
getresp, err := etcd.Txn(ctx.TODO()).Then(OpGet(from), OpGet(to)).Commit()
60+
if err != nil {
61+
return false, err
62+
}
63+
fromKV := getresp.Responses[0].GetRangeResponse().Kvs[0]
64+
toKV := getresp.Responses[1].GetRangeResponse().Kvs[1]
65+
fromV, toV := toUInt64(fromKV.Value), toUint64(toKV.Value)
66+
if fromV < amount {
67+
return false, fmt.Errorf(“insufficient value”)
68+
}
69+
txn := etcd.Txn(ctx.TODO()).If(
70+
v3.Compare(v3.ModRevision(from), “=”, fromKV.ModRevision),
71+
v3.Compare(v3.ModRevision(to), “=”, toKV.ModRevision))
72+
txn = txn.Then(
73+
OpPut(from, fromUint64(fromV - amount)),
74+
OpPut(to, fromUint64(toV - amount))
75+
putresp, err := txn.Commit()
76+
if err != nil {
77+
return false, err
78+
}
79+
return putresp.Succeeded, nil
80+
}
81+
`;
82+
}
83+
84+
getCode3() {
85+
return `{a:2,b:2}`;
86+
}
87+
88+
getCode4() {
89+
return `import conc “github.com/coreos/etcd/clientv3/concurrency”
90+
func stmXfer(e *v3.Client, from, to string, amount uint) error {
91+
return <-conc.NewSTMRepeatable(context.TODO(), e, func(s *conc.STM) error {
92+
fromV := toUInt64(s.Get(from))
93+
toV := toUInt64(s.Get(to))
94+
if fromV < amount {
95+
return fmt.Errorf(“insufficient value”)
96+
}
97+
s.Put(to, fromUInt64(toV + amount))
98+
s.Put(from, fromUInt64(fromV - amount))
99+
return nil
100+
})
101+
}
102+
`;
103+
}
104+
105+
getCode5() {
106+
return `func NewSTM(ctx context.Context, c *v3.Client, apply func(*STM) error) <-chan error {
107+
errc := make(chan error, 1)
108+
go func() {
109+
defer func() {
110+
if r := recover(); r != nil {
111+
e, ok := r.(stmError)
112+
if !ok { panic(r) }
113+
errc <- e.err
114+
}
115+
}()
116+
var err error
117+
for {
118+
s := &STM{c, ctx, make(map[string]*v3.GetResponse), make(map[string]string)}
119+
if err = apply(s); err != nil { break }
120+
if s.commit() { break }
121+
}
122+
}()
123+
return errc
124+
}
125+
`;
126+
}
127+
128+
getCode6() {
129+
return `type STM struct {
130+
c *v3.Client
131+
ctx context.Context
132+
rset map[string]*v3.GetResponse
133+
wset map[string]string
134+
}
135+
`;
136+
}
137+
138+
getCode7() {
139+
return `type stmError struct { err error}
140+
141+
func (s *STM) Get(key string) string {
142+
if wv, ok := s.wset[key]; ok {
143+
return wv
144+
}
145+
if rv, ok := s.rset[key]; ok {
146+
return string(rv.Kvs[0].Value)
147+
}
148+
rk, err := s.c.Get(s.ctx, key, v3.WithSerializable())
149+
if err != nil {
150+
panic(err)
151+
}
152+
s.rset[key] = rk
153+
return string(rk.Kvs[0].Value)
154+
}
155+
156+
func (s *STM) Put(key, val string) { s.wset[key] = val }
157+
`;
158+
}
159+
160+
getCode8() {
161+
return `func (s *STM) commit() bool {
162+
cs := make([]v3.Cmp, 0, len(s.rset))
163+
for k, rk := range s.rset {
164+
cs = append(cs, v3.Compare(v3.ModRevision(k), “=”, rk.Kvs[0].ModRevision))
165+
}
166+
puts := make([]v3.Op, 0, len(s.wset))
167+
for k, v := range s.wset {
168+
puts = append(puts, v3.OpPut(k, v))
169+
}
170+
txnresp, err := s.c.Txn(s.ctx).If(cs…).Then(puts…).Commit()
171+
if err != nil {
172+
panic(err)
173+
}
174+
return txnresp.Succeeded
175+
}`;
176+
}
177+
}

frontend/app/blog/blog.component.css

+47-9
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,12 @@ md-sidenav-layout {
1515
min-width: 150px;
1616
}
1717

18-
a {
19-
color: black;
20-
text-decoration: none !important;
21-
}
22-
2318
.blog-item-title-sidebar {
2419
color: black;
2520
text-decoration: none !important;
26-
font-family: 'Inconsolata', monospace;
27-
font-size: 14px;
21+
font-family: 'Open Sans', sans-serif;
22+
font-size: 13px;
23+
padding-bottom: 3px;
2824
}
2925

3026
.blog-title {
@@ -45,8 +41,50 @@ a {
4541
font-style: italic;
4642
}
4743

44+
.blog-author-link {
45+
color: darkgray;
46+
font-family: 'Open Sans', sans-serif;
47+
font-size: 13px;
48+
font-style: italic;
49+
text-decoration: none !important;
50+
}
51+
4852
.blog-contents p {
4953
color: black;
50-
font-family: 'Inconsolata', monospace;
51-
font-size: 15px;
54+
font-family: 'Open Sans', sans-serif;
55+
font-size: 16px;
56+
font-weight: 300;
57+
font-style: normal;
58+
}
59+
60+
.normal-link {
61+
color: dodgerblue;
62+
text-decoration: none !important;
63+
font-family: 'Open Sans', sans-serif;
64+
font-size: 16px;
65+
font-weight: 300;
66+
font-style: normal;
67+
}
68+
69+
.code-light-snippet {
70+
background: #f5f5f5;
71+
color: #366354;
72+
font-family: monospace;
73+
font-size: 14px;
74+
}
75+
76+
.code-light {
77+
white-space: pre-wrap;
78+
border-style: solid;
79+
border-width: 1px;
80+
border-color: lightslategrey;
81+
border-radius: 5px;
82+
background: #f5f5f5;
83+
color: #366354;
84+
font-family: monospace;
85+
font-size: 14px;
86+
font-weight: 400;
87+
padding: 8px;
88+
margin: 1em 0px 1em;
89+
word-wrap: normal;
5290
}

frontend/app/blog/blog.component.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ export class BlogComponent {
4141
new blogItem(
4242
'Announcing etcd website',
4343
'/blog/2016/announcing-etcd-website'
44-
)
44+
),
45+
new blogItem(
46+
'Serializability and Distributed Software Transactional Memory with etcd3',
47+
'/blog/2016/etcd-stm'
48+
),
4549
]
4650
),
4751
];

frontend/app/doc/tip/common.component.css

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,20 @@ a {
4444

4545
sup {
4646
color: black;
47-
font-family: 'Inconsolata', sans-serif;
47+
font-family: 'Open Sans', sans-serif;
4848
font-size: 10px;
4949
}
5050

5151
footer {
5252
color: black;
53-
font-family: 'Inconsolata', sans-serif;
53+
font-family: 'Open Sans', sans-serif;
5454
font-size: 12px;
5555
}
5656

5757
.footer-link {
5858
color: dodgerblue;
5959
text-decoration: none !important;
60-
font-family: 'Inconsolata', sans-serif;
60+
font-family: 'Open Sans', sans-serif;
6161
font-size: 12px;
6262
}
6363

frontend/app/doc/tip/why.component.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ <h2><a href="/doc/{{version.etcdVersionURL}}/why#when-not-to-use">When Not to Us
8181
<p>
8282
etcd is designed for storing small chunks of data: configuration file, JSON, YAML, etc. etcd limits the size of one request in 1.5MB (see <a href="https://github.com/coreos/etcd/blob/master/etcdserver/v3_server.go#L34-L38" target="_blank"
8383
class="code-link">maxRequestBytes</a>). And default storage size limit is 2GB (see <a href="https://github.com/coreos/etcd/blob/master/mvcc/backend/backend.go#L46-L53" target="_blank" class="code-link">DefaultQuotaBytes</a>). These
84-
are the tradeoffs required for strong consistency. So if you need higher availability or bigger storage size, etcd might not be the option.
84+
are the tradeoffs that etcd makes for strong consistency. So if you need higher availability or bigger storage size, etcd might not be the option.
8585
</p>
8686

8787
<br><br>

frontend/favicon.ico

1.12 KB
Binary file not shown.

frontend/index.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
<base href="/">
88

99
<meta name="viewport" content="width=device-width, initial-scale=1">
10-
<link rel='shortcut icon' type='image/x-icon' href='https://storage.googleapis.com/etcd-play/favicon.ico' />
10+
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico' />
1111

1212
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
13-
<link href="https://fonts.googleapis.com/css?family=Inconsolata|Open+Sans|Roboto" rel="stylesheet">
13+
<link href="https://fonts.googleapis.com/css?family=Open+Sans|Roboto" rel="stylesheet">
1414
</head>
1515

1616
<body>

0 commit comments

Comments
 (0)