-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.go
More file actions
230 lines (205 loc) · 6.58 KB
/
main.go
File metadata and controls
230 lines (205 loc) · 6.58 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
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package main
import (
"database/sql"
"encoding/binary"
"fmt"
"github.com/3th1nk/cidr"
_ "github.com/mattn/go-sqlite3"
"math"
"math/big"
"net"
"os"
"runtime"
"strconv"
"sync"
"time"
)
var stub = make([]byte, 1024 * 1024 * 1024 * 4)
func main(){
destination_host_ip := "123.223.32.4"
destination_host_ip_int := (IP6toInt(net.ParseIP(destination_host_ip)).Int64())
// allow the program to use all cores.
runtime.GOMAXPROCS(runtime.NumCPU())
// allocate memory for the program.
stub[0] = 1
type Row struct {
RowKey string
RowValue int64
}
vni_slice := make([]int, 0)
// add a default VNI to this slice, could add more in the future.
vni_slice = append(vni_slice, 123)
// Create a CIDR for all VPCs
cidr_pointer, _ := cidr.ParseCIDR("2001:0db8:85a3:0000:0000:8a2e:0370:7334/104")
ip_slice := make([]string, 0)
if cidr_pointer.IsIPv4(){
fmt.Println("We have IPV4 address!")
cidr_pointer.ForEachIP(func(ip string) error {
//for _, vni := range vni_slice {
//
// ip_plus_vni_int := IP6VniToInt(net.ParseIP(ip), int64(vni))
// fmt.Println(ip_plus_vni_int.Bytes())
// ip_slice = append(ip_slice, ip_plus_vni_int)
//}
ip_slice = append(ip_slice, (IP6toInt(net.ParseIP(ip)).String()))
return nil
})
}else if cidr_pointer.IsIPv6(){
fmt.Println("We have IPV6 address!")
cidr_pointer.ForEachIP(func(ip string) error {
//for _, vni := range vni_slice {
//
// ip_plus_vni_int := IP6VniToInt(net.ParseIP(ip), int64(vni))
// fmt.Println(ip_plus_vni_int.Bytes())
// ip_slice = append(ip_slice, ip_plus_vni_int)
//}
ip_slice = append(ip_slice, ip)
return nil
})
}else{
panic("This CIDR is neither v4 nor v6, existing")
}
fmt.Printf("There are %v IPs in this CIDR %s\n", len(ip_slice), cidr_pointer.CIDR())
number_of_go_routines := 20
// Open the connection to the DB, will create the .db file is it does not exist.
db, err := sql.Open("sqlite3", "file:./rio_testing.db?loc=auto&_journal_mode=wal&_mutex=no")
// one DB connection can be used by two go-routines
number_of_db_connections := int(math.Ceil(float64(number_of_go_routines) / 2.0))
db_connections := make([]*sql.DB, number_of_db_connections)
// create multiple db connections for concurrent read.
for i := 0 ; i < number_of_db_connections ; i ++{
db_connections[i],_ = sql.Open("sqlite3", "file:./rio_testing.db?loc=auto&_journal_mode=wal&_mutex=no")
}
db.SetMaxOpenConns(1)
if err != nil {
fmt.Println("SQLite:", err)
}
fmt.Println("SQLite start")
//Create the table, INTEGER key and INTEGER value
// add mac address, put VNI at first
sqlStmt := `create table IF NOT EXISTS BC (RowKey TEXT not null primary key, RowKeyTwo INTEGER not null, RowValue INTEGER not null);`
_, err = db.Exec(sqlStmt)
if err != nil {
fmt.Printf("create table error->%q: %s\n", err, sqlStmt)
return
}
//Create index on column 1, index on neighbor_ip and VNI
_, err = db.Exec("CREATE INDEX index_row_key ON BC(RowKey, RowKeyTwo);")
if err != nil {
fmt.Println("create index error->%q: %s\n", err, sqlStmt)
return
}
//Create index on column 2
//_, err = db.Exec("CREATE INDEX index_row_key_two ON BC(RowKeyTwo);")
//if err != nil {
// fmt.Println("create index error->%q: %s\n", err, sqlStmt)
// return
//}
//Start time measuring
start := time.Now().Unix()
tx, err := db.Begin()
if err != nil {
fmt.Printf("%q\n", err)
}
// prepare insert statement
stmt, err := tx.Prepare("insert into BC(RowKey, RowKeyTwo, RowValue) values(?,?,?)")
if err != nil {
fmt.Printf("insert err %q\n", err)
}
db.Close()
defer stmt.Close()
var m int = len(ip_slice)//1000 * 1000
var total int = 1 * m
for i := 0; i < total; i++ {
_, err = stmt.Exec(ip_slice[i], vni_slice[0], destination_host_ip_int)
if err != nil {
fmt.Printf("Insert error: %q", err)
}
}
tx.Commit()
insertEnd := time.Now().Unix()
// Start the querying
wg := sync.WaitGroup{}
// Prepare the select statements for each db read connection.
query_statements := make([]*sql.Stmt, number_of_db_connections)
for i := 0 ; i < number_of_db_connections ; i ++{
query_statements[i], _ = db_connections[i].Prepare("select RowValue from BC where RowKey = ? AND RowKeyTwo = ? ")
}
// Start querying in each go-routine, each go-routine query `total` times.
for i := 0 ; i < number_of_go_routines ; i ++ {
wg.Add(1)
go func(i int, query_statement *sql.Stmt) {
query_start := time.Now().Unix()
var count int64 = 0
fmt.Printf("Starting go-routine %d\n", i)
if err != nil {
fmt.Println("select err %q", err)
}
//bc := new(BCCode)
var b int64
for j := 0; j < total; j++ {
//var rowCount int
err := query_statement.QueryRow(ip_slice[i], vni_slice[0]).Scan(&b)
if err != nil {
fmt.Printf("query err %q", err)
os.Exit(-1)
}
/* Comment out the converting code for testing purpose.
fmt.Printf("IP: %v\n", ip_slice[i])
//c := net.IP(big.NewInt(b).Bytes())
// Comment out the outputs, as it slows down the code.
b0 := strconv.FormatInt((b>>24)&0xff, 10)
b1 := strconv.FormatInt((b>>16)&0xff, 10)
b2 := strconv.FormatInt((b>>8)&0xff, 10)
b3 := strconv.FormatInt((b & 0xff), 10)
fmt.Printf("%v.%v.%v.%v\n", b0, b1, b2, b3 )
*/
count++
}
readEnd := time.Now().Unix()
fmt.Println("go-routine: ", i , "insert span=", (insertEnd - start),
"read span=", (readEnd - query_start),
"avg read=", float64(readEnd-query_start)*1000/float64(count))
wg.Done()
}(i, query_statements[i % number_of_db_connections])
}
wg.Wait()
fmt.Println("All finished.")
}
//Copied from https://go.dev/play/p/JVJuTsxXR-
func padding(n int32) int32 {
var p int32 = 1
for p < n {
p *= 10
}
return p
}
//func ip2Long(ip string) uint32 {
// var long uint32
// binary.Read(bytes.NewBuffer(net.ParseIP(ip).To4()), binary.BigEndian, &long)
// return long
//}
func IP6toInt(IPv6Address net.IP) *big.Int {
IPv6Int := big.NewInt(0)
// from http://golang.org/pkg/net/#pkg-constants
// IPv6len = 16
IPv6Int.SetBytes(IPv6Address.To16())
return IPv6Int
}
func IP6VniToInt(IPv6Address net.IP, vni int64) *big.Int {
IPv6Int := big.NewInt(0)
// from http://golang.org/pkg/net/#pkg-constants
// IPv6len = 16
vni_bytes := make([]byte, 8)
binary.LittleEndian.PutUint64(vni_bytes, big.NewInt(vni).Uint64())
IPv6Int.SetBytes(append(IPv6Address.To16(), vni_bytes... ))
return IPv6Int
}
func backtoIP4(ipInt int64) string {
// need to do two bit shifting and “0xff” masking
b0 := strconv.FormatInt((ipInt>>24)&0xff, 10)
b1 := strconv.FormatInt((ipInt>>16)&0xff, 10)
b2 := strconv.FormatInt((ipInt>>8)&0xff, 10)
b3 := strconv.FormatInt((ipInt & 0xff), 10)
return b0 + "." + b1 + "." + b2 + "." + b3
}