forked from couchbase/gocb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
connspec.go
115 lines (97 loc) · 2.44 KB
/
connspec.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package gocb
import (
"fmt"
"net"
"regexp"
"strconv"
)
// A single address stored within a connection string
type connSpecAddr struct {
Host string
Port uint16
}
// A parsed connection string
type connSpec struct {
Scheme string
Hosts []connSpecAddr
Bucket string
Options map[string]string
}
// Parses a connection string into a structure more easily consumed by the library.
func parseConnSpec(connStr string) connSpec {
var out connSpec
out.Options = map[string]string{}
partMatcher := regexp.MustCompile(`((.*):\/\/)?([^\/?]*)(\/([^\?]*))?(\?(.*))?`)
hostMatcher := regexp.MustCompile(`([^;\,\:]+)(:([0-9]*))?(;\,)?`)
kvMatcher := regexp.MustCompile(`([^=]*)=([^&?]*)[&?]?`)
parts := partMatcher.FindStringSubmatch(connStr)
if parts[2] != "" {
out.Scheme = parts[2]
}
if parts[3] != "" {
hosts := hostMatcher.FindAllStringSubmatch(parts[3], -1)
for _, hostInfo := range hosts {
port := 0
if hostInfo[3] != "" {
port, _ = strconv.Atoi(hostInfo[3])
}
out.Hosts = append(out.Hosts, connSpecAddr{
Host: hostInfo[1],
Port: uint16(port),
})
}
}
if parts[5] != "" {
out.Bucket = parts[5]
}
if parts[7] != "" {
kvs := kvMatcher.FindAllStringSubmatch(parts[7], -1)
for _, kvInfo := range kvs {
out.Options[kvInfo[1]] = kvInfo[2]
}
}
return out
}
func csResolveDnsSrv(spec *connSpec) bool {
if len(spec.Hosts) == 1 && spec.Hosts[0].Port == 0 && (spec.Scheme == "couchbase" || spec.Scheme == "couchbases") {
srvHostname := spec.Hosts[0].Host
_, addrs, err := net.LookupSRV(spec.Scheme, "tcp", srvHostname)
if err != nil {
return false
}
var hostList []connSpecAddr
for _, srvRecord := range addrs {
hostList = append(hostList, connSpecAddr{srvRecord.Target, srvRecord.Port})
}
spec.Hosts = hostList
return true
} else {
return false
}
}
// Guesses a list of memcached hosts based on a connection string specification structure.
func csGetMemdHosts(spec connSpec) []connSpecAddr {
var out []connSpecAddr
for _, host := range spec.Hosts {
memdHost := connSpecAddr{
Host: host.Host,
Port: 0,
}
fmt.Printf("Host parse: %s:%d", host.Host, host.Port)
if host.Port == 0 {
if spec.Scheme != "couchbases" {
memdHost.Port = 11210
} else {
memdHost.Port = 11207
}
} else if host.Port == 8091 {
memdHost.Port = 11210
} else if host.Port == 18091 {
memdHost.Port = 11207
}
if memdHost.Port != 0 {
out = append(out, memdHost)
}
}
return out
}