-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbolthandler.go
174 lines (146 loc) · 4.22 KB
/
bolthandler.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package main
import (
"encoding/json"
"fmt"
"log"
"os"
"time"
"github.com/httpreserve/httpreserve"
kval "github.com/kval-access-language/kval-bbolt"
"github.com/speps/go-hashids"
)
// values to use to create hashid
var salt = "httpreserve"
var namelen = 8
// bucket constants
const linkIndex = "link index"
// const fnameIndex = "filename index"
const hashIndex = "hash index"
// location for bolt databases. Names are random at present because
// I'm unsure how they're going to be used in future so may write naming
// functions and flags at a later date.
const boltdir = "db/"
// For stdout the name of the database
var boltoutput string
// getNewDBName provides three integers based on the time at
// which we run the code to help us create a hashid name for the db.
func getNewDBName() []int {
t := time.Now()
i1 := t.Minute()
i2 := t.Second()
i3 := t.Nanosecond()
return []int{i1, i2, i3}
}
// configureHashID will create a hashids name for our database
func configureHashID() string {
name := getNewDBName()
//hashdata
hd := hashids.NewData()
hd.Salt = salt
hd.MinLength = namelen
//hash
h, _ := hashids.NewWithData(hd)
e, _ := h.Encode(name)
return e
}
// makeIDIndex will write rows to the BoldDB based on an MD5 hash value
// associated with the lmap passed to the function (a deconstructed LinkStats)
func makeIDIndex(kb kval.Kvalboltdb, lmap map[string]interface{}) {
for k, v := range lmap {
_, err := kval.Query(kb, "INS "+convertInterface(lmap["response code"])+">>"+convertInterface(lmap["link"])+" >>>> "+k+" :: "+convertInterface(v))
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
}
}
// makeBoltDir will create a database for all BoldDB files generated
// if the database doesn't already exist.
func makeBoltDir() {
if _, err := os.Stat(boltdir); os.IsNotExist(err) {
err := os.Mkdir(boltdir, 0700)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
}
// boltGetResultContainers returns the names of all top level buckets
// n.b. these functions are heavily linked to the database schema and
// could be made more generic with more effort.
func boltGetResultContainers(kb kval.Kvalboltdb) []string {
var buckets []string
q := "GET " + hashIndex
res, _ := kval.Query(kb, q)
for k := range res.Result {
buckets = append(buckets, k)
}
return buckets
}
// boltGetSingleRecord will return a single record for a given md5 key
// n.b. these functions are heavily linked to the database schema and
// could be made more generic with more effort.
func boltGetSingleRecord(kb kval.Kvalboltdb, md5Key string) map[string]string {
records := make(map[string]string)
q := "GET " + hashIndex + " >> " + md5Key
res, _ := kval.Query(kb, q)
for k, v := range res.Result {
records[k] = v
}
return records
}
// boltGetAllRecords returns all records in all top level buckets in the
// database.
// n.b. these functions are heavily linked to the database schema and
// could be made more generic with more effort.
func boltGetAllRecords(kb kval.Kvalboltdb) []map[string]string {
var records []map[string]string
keys := boltGetResultContainers(kb)
for _, v := range keys {
records = append(records, boltGetSingleRecord(kb, v))
}
return records
}
var kb kval.Kvalboltdb
func openKVALBolt() {
var err error
boltname := configureHashID()
makeBoltDir()
boltoutput = boltdir + "HP_" + boltname + ".bolt"
kb, err = kval.Connect(boltoutput)
if err != nil {
fmt.Fprintf(os.Stderr, "Error opening bolt database: %+v\n", err)
os.Exit(1)
}
}
func closeKVALBolt() {
kval.Disconnect(kb)
}
var id []string
// boltdbHandler is the primary handler for writing to a BoltDB
// from our httpreserve results rsets.
func boltdbHandler(js string) {
var ls httpreserve.LinkStats
err := json.Unmarshal([]byte(js), &ls)
if err != nil {
fmt.Fprintln(os.Stderr, "problem unmarshalling data.", err)
}
var add = true
// retrieve a map from the structure and write it out to the
// bolt db.
lmap := storeStruct(ls, js)
if len(lmap) > 0 {
makeIDIndex(kb, lmap)
lmapid := convertInterface(lmap["id"])
for x := range id {
if lmapid == id[x] {
add = false
log.Println("Already seen:", lmap["filename"], lmap["title"])
break
}
}
if add {
makeIDIndex(kb, lmap)
id = append(id, lmapid)
}
}
}