-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
44d38cb
commit 043613d
Showing
6 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package udp | ||
|
||
import "github.com/influxdb/influxdb/toml" | ||
|
||
type Config struct { | ||
Enabled bool `toml:"enabled"` | ||
BindAdress string `toml:"bind-adress"` | ||
Port int `toml:"port"` | ||
|
||
Database string `toml:"database"` | ||
BatchSize int `toml:"batch-size"` | ||
BatchTimeout toml.Duration `toml:"batch-timeout"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package udp | ||
|
||
import ( | ||
"net" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
type Service struct { | ||
Server *Server | ||
|
||
iface string | ||
} | ||
|
||
func NewService(c Config) *Service { | ||
server := NewServer(c.Database) | ||
server.SetBatchSize(c.BatchSize) | ||
server.SetBatchTimeout(time.Duration(c.BatchTimeout)) | ||
|
||
return &Service{ | ||
iface: net.JoinHostPort(c.BindAdress, strconv.Itoa(c.Port)), | ||
Server: server, | ||
} | ||
} | ||
|
||
func (s *Service) Open() error { | ||
return s.Server.ListenAndServe(s.iface) | ||
} | ||
|
||
func (s *Service) Close() error { | ||
return s.Server.Close() | ||
} | ||
|
||
func (s *Service) Addr() net.Addr { | ||
return s.Server.Addr() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package udp | ||
|
||
import ( | ||
"log" | ||
"net" | ||
"os" | ||
"sync" | ||
"time" | ||
|
||
"github.com/influxdb/influxdb/cluster" | ||
"github.com/influxdb/influxdb/tsdb" | ||
) | ||
|
||
const ( | ||
udpBufferSize = 65536 | ||
) | ||
|
||
type Server struct { | ||
conn *net.UDPConn | ||
addr *net.UDPAddr | ||
wg sync.WaitGroup | ||
|
||
batchSize int | ||
batchTimeout time.Duration | ||
database string | ||
|
||
PointsWriter interface { | ||
WritePoints(p *cluster.WritePointsRequest) error | ||
} | ||
|
||
Logger *log.Logger | ||
} | ||
|
||
func NewServer(db string) *Server { | ||
return &Server{ | ||
database: db, | ||
Logger: log.New(os.Stderr, "[udp] ", log.LstdFlags), | ||
} | ||
} | ||
|
||
func (s *Server) SetBatchSize(sz int) { s.batchSize = sz } | ||
func (s *Server) SetBatchTimeout(d time.Duration) { s.batchTimeout = d } | ||
|
||
func (s *Server) ListenAndServe(iface string) (err error) { | ||
s.addr, err = net.ResolveUDPAddr("udp", iface) | ||
if err != nil { | ||
s.Logger.Printf("Failed to resolve UDP address %s: %s", iface, err) | ||
return err | ||
} | ||
|
||
s.conn, err = net.ListenUDP("udp", s.addr) | ||
if err != nil { | ||
s.Logger.Printf("Failed to set up UDP listener at address %s: %s", s.addr, err) | ||
return err | ||
} | ||
|
||
s.Logger.Printf("Started listening on %s", iface) | ||
|
||
batcher := tsdb.NewPointBatcher(s.batchSize, s.batchTimeout) | ||
batcher.Start() | ||
|
||
// Start processing batches. | ||
var wg sync.WaitGroup | ||
done := make(chan struct{}) | ||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
for { | ||
select { | ||
case batch := <-batcher.Out(): | ||
err = s.PointsWriter.WritePoints(&cluster.WritePointsRequest{ | ||
Database: s.database, | ||
RetentionPolicy: "", | ||
ConsistencyLevel: cluster.ConsistencyLevelOne, | ||
Points: batch, | ||
}) | ||
if err != nil { | ||
s.Logger.Printf("Failed to write point batch to database %q: %s\n", s.database, err) | ||
} else { | ||
s.Logger.Printf("Wrote a batch of %d points to %s", len(batch), s.database) | ||
} | ||
case <-done: | ||
return | ||
} | ||
} | ||
}() | ||
|
||
s.wg.Add(1) | ||
go func() { | ||
defer s.wg.Done() | ||
for { | ||
buf := make([]byte, udpBufferSize) | ||
n, _, err := s.conn.ReadFromUDP(buf) | ||
if err != nil { | ||
s.Logger.Printf("Failed to read UDP message: %s", err) | ||
batcher.Flush() | ||
close(done) | ||
wg.Wait() | ||
return | ||
} | ||
|
||
points, err := tsdb.ParsePoints(buf[:n]) | ||
if err != nil { | ||
s.Logger.Printf("Failed to parse points: %s", err) | ||
continue | ||
} | ||
|
||
s.Logger.Printf("Received write for %d points on database %s", len(points), s.database) | ||
|
||
for _, point := range points { | ||
batcher.In() <- point | ||
} | ||
} | ||
}() | ||
|
||
return nil | ||
} | ||
|
||
func (s *Server) Close() error { | ||
var err error | ||
if s.conn != nil { | ||
err = s.conn.Close() | ||
} | ||
s.wg.Done() | ||
|
||
return err | ||
} | ||
|
||
func (s *Server) Addr() net.Addr { | ||
return s.addr | ||
} |