-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquery.go
More file actions
128 lines (110 loc) · 3.05 KB
/
query.go
File metadata and controls
128 lines (110 loc) · 3.05 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
package gosMAP
import (
"bytes"
"encoding/json"
"fmt"
"hash/fnv"
"io/ioutil"
"net/http"
"github.com/bradfitz/gomemcache/memcache"
)
func (conn *Connection) query(q string) []byte {
url := fmt.Sprintf("%sapi/query?key=%s", conn.Url, conn.APIkey)
response, err := http.Post(url, "text/smap", bytes.NewBufferString(q))
if err != nil {
return nil
}
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil
}
return contents
}
func queryKey(q string) string {
h := fnv.New32a()
h.Write([]byte("query"))
h.Write([]byte(q))
return fmt.Sprintf("%d", h.Sum32())
}
func (conn *Connection) cacheGet(q string) (b []byte, err error) {
key := queryKey(q)
if conn.Mc != nil {
item, lerr := conn.Mc.Get(key)
if lerr == nil && item != nil {
return item.Value, nil
}
err = fmt.Errorf("Cache miss")
} else {
err = fmt.Errorf("Not using cache")
}
return b, err
}
// Query using sMAP querying language
//
// See http://www.cs.berkeley.edu/~stevedh/smap2/archiver.html#archiverquery for further
// documentation to retrieve data. The contents will be returned as json text if success,
// and on some errors a text file
func (conn *Connection) Query(q string) (results []RawData, err error) {
key := queryKey(q)
var raw []RawData
b, err := conn.cacheGet(q)
if err == nil {
// Cache Hit
err = json.Unmarshal(b, &raw)
} else {
// Cache Miss
b := conn.query(q)
err = json.Unmarshal(b, &raw)
if err == nil && conn.Mc != nil {
var savebin []byte
// Save in the cache
savebin, err = json.Marshal(raw)
// Save
if err == nil {
err = conn.Mc.Set(&memcache.Item{Key: key, Value: savebin, Expiration: 3600})
} else {
return raw, err
}
}
}
return raw, err
}
// QueryList is a query that returns a string array. This is necessary for
// for all ```select distinct``` queries.
func (conn *Connection) QueryList(q string) (results []string, err error) {
key := queryKey(q)
b, err := conn.cacheGet(q)
if err == nil {
// Cache hit
err = json.Unmarshal(b, &results)
} else {
// Cache miss
b := conn.query(q)
err = json.Unmarshal(b, &results)
//Save
if err == nil && conn.Mc != nil {
conn.Mc.Set(&memcache.Item{Key: key, Value: b, Expiration: 3600})
}
}
return results, err
}
// Get data given a uuid.
//
// starttime and endtime are unix times in seconds based off of the epoch. A
// starttime of 0 will get data starting from the first entry and a endtime of
// 0 will have no upper bound. Limit is the number of values to be retrieved.
// Set to 0 if you do not want a limit.
//
// Although the return is an array of SMAPData, typically there should only be
// one value with the given uuid.
func (conn *Connection) Get(uuid string, starttime int, endtime int, limit int) ([]RawData, error) {
starttimeStr := smap_time(starttime)
// endtime doesn't work
if endtime == 0 {
endtime = 2000000000000
}
endtimeStr := smap_time(endtime)
url := fmt.Sprintf("%sapi/data/uuid/%s?startime=%s&endtime=%s&limit=%d", conn.Url, uuid, starttimeStr, endtimeStr, limit)
return pullData(url)
}