Skip to content

Commit 436a20b

Browse files
committed
Initial Commit
1 parent a603c49 commit 436a20b

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

client.go

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package client
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
"fmt"
7+
"io"
8+
"net"
9+
"time"
10+
)
11+
12+
type LockingCenter interface {
13+
Lock(key string)
14+
Unlock(key string)
15+
Wait(key string)
16+
Reset(key string)
17+
}
18+
19+
type lockingCenter struct {
20+
address *net.TCPAddr
21+
}
22+
23+
func NewLockingCenter(address string) (LockingCenter, error) {
24+
addr, err := net.ResolveTCPAddr("tcp", address)
25+
if err != nil {
26+
return nil, err
27+
}
28+
29+
lc := &lockingCenter{
30+
address: addr,
31+
}
32+
if err := lc.ping(); err != nil {
33+
return nil, err
34+
}
35+
return lc, nil
36+
}
37+
38+
func (l *lockingCenter) connect() (*net.TCPConn, error) {
39+
conn, err := net.DialTCP("tcp", nil, l.address)
40+
if err != nil {
41+
return nil, err
42+
}
43+
return conn, nil
44+
}
45+
46+
func (l *lockingCenter) ping() error {
47+
conn, err := l.connect()
48+
if err != nil {
49+
return err
50+
}
51+
return conn.Close()
52+
}
53+
54+
func (l *lockingCenter) preparePackage(key string, action byte) ([]byte, error) {
55+
if len(key) == 0 || len(key) > 128 {
56+
return nil, fmt.Errorf("key can not be empty or more than 128 characters")
57+
}
58+
59+
data := make([]byte, 0)
60+
buffer := bytes.NewBuffer(data)
61+
62+
keySize := int8(len(key))
63+
if err := binary.Write(buffer, binary.LittleEndian, keySize); err != nil {
64+
return nil, err
65+
}
66+
67+
if err := binary.Write(buffer, binary.LittleEndian, []byte(key)); err != nil {
68+
return nil, err
69+
}
70+
71+
if err := binary.Write(buffer, binary.LittleEndian, action); err != nil {
72+
return nil, err
73+
}
74+
75+
return buffer.Bytes(), nil
76+
}
77+
78+
func (l *lockingCenter) result(conn *net.TCPConn) bool {
79+
r := make([]byte, 1)
80+
81+
if _, err := io.ReadAtLeast(conn, r, len(r)); err != nil {
82+
return false
83+
}
84+
85+
return string(r) == "+"
86+
}
87+
88+
func (l *lockingCenter) Lock(key string) {
89+
query := func() bool {
90+
conn, err := l.connect()
91+
if err != nil {
92+
fmt.Printf("ERROR: connection failure: %s\n", err)
93+
return false
94+
}
95+
defer conn.Close()
96+
97+
if err := l.query(conn, key, 1); err != nil {
98+
fmt.Printf("ERROR: locking error: %s\n", err)
99+
return false
100+
}
101+
102+
return true
103+
}
104+
105+
for !query() {
106+
time.Sleep(time.Second)
107+
}
108+
}
109+
110+
func (l *lockingCenter) Unlock(key string) {
111+
query := func() bool {
112+
conn, err := l.connect()
113+
if err != nil {
114+
fmt.Printf("ERROR: connection failure: %s\n", err)
115+
return false
116+
}
117+
defer conn.Close()
118+
119+
if err := l.query(conn, key, 2); err != nil {
120+
fmt.Printf("ERROR: unlocking error: %s\n", err)
121+
return false
122+
}
123+
124+
return true
125+
}
126+
127+
for !query() {
128+
time.Sleep(time.Second)
129+
}
130+
}
131+
132+
func (l *lockingCenter) Wait(key string) {
133+
l.Lock(key)
134+
defer l.Unlock(key)
135+
}
136+
137+
func (l *lockingCenter) Reset(key string) {
138+
query := func() bool {
139+
conn, err := l.connect()
140+
if err != nil {
141+
fmt.Printf("ERROR: connection failure: %s\n", err)
142+
return false
143+
}
144+
defer conn.Close()
145+
146+
if err := l.query(conn, key, 3); err != nil {
147+
fmt.Printf("ERROR: reseting error: %s\n", err)
148+
return false
149+
}
150+
151+
return true
152+
}
153+
154+
for !query() {
155+
time.Sleep(time.Second)
156+
}
157+
}
158+
159+
func (l *lockingCenter) query(conn *net.TCPConn, key string, action byte) error {
160+
payload, err := l.preparePackage(key, action)
161+
if err != nil {
162+
return err
163+
}
164+
165+
if _, err := conn.Write(payload); err != nil {
166+
return err
167+
}
168+
169+
if !l.result(conn) {
170+
return fmt.Errorf("remote server execution error")
171+
}
172+
173+
return nil
174+
}

go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/freakmaxi/locking-center
2+
3+
go 1.14

0 commit comments

Comments
 (0)