This repository was archived by the owner on Dec 17, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwrite.go
161 lines (116 loc) · 3.65 KB
/
write.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
package main
import (
"encoding/binary"
"io"
"log"
"os"
"runtime"
wp "github.com/gammazero/workerpool"
)
// SequentialWriteToFile - Given file name and number of protocol buffer
// entries to be written to file, it'll sequentially write those many entries
// into file
func SequentialWriteToFile(file string, count int) bool {
// truncating/ opening for write/ creating data file, where to store protocol buffer encoded data
fd, err := os.OpenFile(file, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
log.Printf("[!] Error : %s\n", err.Error())
return false
}
// to be invoked when returning from this function scope
defer fd.Close()
for i := 0; i < count; i++ {
data := Serialize(NewCPU())
if data == nil {
return false
}
// store size of message ( in bytes ), in a byte array first
// then that's to be written on file handle
buf := make([]byte, 4)
binary.LittleEndian.PutUint32(buf, uint32(len(data)))
// first write size of proto message in 4 byte space
if _, err := fd.Write(buf); err != nil {
log.Printf("[!] Error : %s\n", err.Error())
break
}
// then write actual message
if _, err := fd.Write(data); err != nil {
log.Printf("[!] Error : %s\n", err.Error())
break
}
}
return true
}
// ConcurrentWriteAllToFile - Concurrently generate random CPU data `count` times
// using worker pool and write them in data file provided
//
// Nothing but concurrent implementation of above function, but file writer is
// working sequentially
func ConcurrentWriteAllToFile(file string, count int) bool {
// Truncating/ opening for write/ creating data file, where to store protocol buffer encoded data
fd, err := os.OpenFile(file, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
log.Printf("[!] Error : %s\n", err.Error())
return false
}
// to be invoked when returning from this function scope
defer fd.Close()
pool := wp.New(runtime.NumCPU())
data := make(chan []byte, count)
done := make(chan bool)
go WriteCPUDataToFile(fd, count, data, done)
for i := 0; i < count; i++ {
pool.Submit(func() {
data <- Serialize(NewCPU())
})
}
pool.StopWait()
// Blocking call i.e. waiting for writer go routine
// to complete its job
<-done
return true
}
// WriteCPUDataToFile - Receives binary data to be written to file over
// go channel and writes that along with respective size of data
//
// Writing size is important because while deserializing we'll require
// that
func WriteCPUDataToFile(fd io.Writer, count int, data chan []byte, done chan bool) {
// Letting coordinator know writing to file has been completed
// or some kind of error has occurred
//
// To be invoked when getting out of this execution scope
defer func() {
done <- true
}()
// How many data chunks received over channel
//
// To be compared against data chunks which were supposed
// to be received, before deciding whether it's time to get out of
// below loop or not
var iter int
for d := range data {
// received new data which needs to be written to file
iter++
// store size of message ( in bytes ), in a byte array first
// then that's to be written on file handle
buf := make([]byte, 4)
binary.LittleEndian.PutUint32(buf, uint32(len(d)))
// first write size of proto message in 4 byte space
if _, err := fd.Write(buf); err != nil {
log.Printf("[!] Error : %s\n", err.Error())
break
}
// then write actual message
if _, err := fd.Write(d); err != nil {
log.Printf("[!] Error : %s\n", err.Error())
break
}
// As soon as this condition is met,
// we can safely get out of this loop
// i.e. denoting all processing has been done
if iter == count {
break
}
}
}