parent
c702388603
commit
02f8a9a370
@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
type Int64 struct {
|
||||
v int64
|
||||
}
|
||||
|
||||
func (a *Int64) Get() int64 {
|
||||
return atomic.LoadInt64(&a.v)
|
||||
}
|
||||
|
||||
func (a *Int64) Set(v int64) {
|
||||
atomic.StoreInt64(&a.v, v)
|
||||
}
|
||||
|
||||
func (a *Int64) CompareAndSwap(o, n int64) bool {
|
||||
return atomic.CompareAndSwapInt64(&a.v, o, n)
|
||||
}
|
||||
|
||||
func (a *Int64) Swap(v int64) int64 {
|
||||
return atomic.SwapInt64(&a.v, v)
|
||||
}
|
||||
|
||||
func (a *Int64) Add(v int64) int64 {
|
||||
return atomic.AddInt64(&a.v, v)
|
||||
}
|
||||
|
||||
func (a *Int64) Sub(v int64) int64 {
|
||||
return a.Add(-v)
|
||||
}
|
||||
|
||||
func (a *Int64) Incr() int64 {
|
||||
return a.Add(1)
|
||||
}
|
||||
|
||||
func (a *Int64) Decr() int64 {
|
||||
return a.Add(-1)
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// BufferPool implements a pool of bytes.Buffers in the form of a bounded
|
||||
// channel.
|
||||
type BufferPool struct {
|
||||
c chan *bytes.Buffer
|
||||
}
|
||||
|
||||
// NewBufferPool creates a new BufferPool bounded to the given size.
|
||||
func NewBufferPool(size int) (bp *BufferPool) {
|
||||
return &BufferPool{
|
||||
c: make(chan *bytes.Buffer, size),
|
||||
}
|
||||
}
|
||||
|
||||
// Get gets a Buffer from the BufferPool, or creates a new one if none are
|
||||
// available in the pool.
|
||||
func (bp *BufferPool) Get() (b *bytes.Buffer) {
|
||||
select {
|
||||
case b = <-bp.c:
|
||||
// reuse existing buffer
|
||||
default:
|
||||
// create new buffer
|
||||
b = bytes.NewBuffer([]byte{})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Put returns the given Buffer to the BufferPool.
|
||||
func (bp *BufferPool) Put(b *bytes.Buffer) {
|
||||
b.Reset()
|
||||
select {
|
||||
case bp.c <- b:
|
||||
default: // Discard the buffer if the pool is full.
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
hash: b098305412c9c0105d572881e395da369b0acf7738d1e89eb816b1e69f731aca
|
||||
updated: 2018-01-16T10:18:20.068657958+08:00
|
||||
imports:
|
||||
- name: github.com/codeskyblue/gosuv
|
||||
version: 6f18d35abfca2d1b82e522ea868771436341dd8e
|
||||
subpackages:
|
||||
- pushover
|
||||
- name: github.com/codeskyblue/kexec
|
||||
version: 863094f94c7fb7c235764bf8f0f79cccea78c8eb
|
||||
- name: github.com/equinox-io/equinox
|
||||
version: f24972fa72facf59d05c91c848b65eac38815915
|
||||
- name: github.com/franela/goreq
|
||||
version: bcd34c9993f899273c74baaa95e15386cd97b6e7
|
||||
- name: github.com/glycerine/rbuf
|
||||
version: 54320fe9f6f340f8fbe3f34306e3c32589d97dc4
|
||||
- name: github.com/go-yaml/yaml
|
||||
version: d670f9405373e636a5a2765eea47fac0c9bc91a4
|
||||
- name: github.com/goji/httpauth
|
||||
version: 2da839ab0f4df05a6db5eb277995589dadbd4fb9
|
||||
- name: github.com/gorilla/context
|
||||
version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42
|
||||
- name: github.com/gorilla/mux
|
||||
version: 5bbbb5b2b5729b132181cc7f4aa3b3c973e9a0ed
|
||||
- name: github.com/gorilla/websocket
|
||||
version: 292fd08b2560ad524ee37396253d71570339a821
|
||||
- name: github.com/kennygrant/sanitize
|
||||
version: 2e6820834a1f36c626bf19a253b7d3cc060e9b8b
|
||||
- name: github.com/lunny/dingtalk_webhook
|
||||
version: e3534c89ef969912856dfa39e56b09e58c5f5daf
|
||||
- name: github.com/mitchellh/go-ps
|
||||
version: 4fdf99ab29366514c69ccccddab5dc58b8d84062
|
||||
- name: github.com/qiniu/log
|
||||
version: a304a74568d6982c5b89de1c68ac8fca3add196a
|
||||
- name: github.com/shirou/gopsutil
|
||||
version: 6a368fb7cd1221fa6ea90facc9447c9a2234c255
|
||||
subpackages:
|
||||
- process
|
||||
- name: github.com/shurcooL/httpfs
|
||||
version: 809beceb23714880abc4a382a00c05f89d13b1cc
|
||||
subpackages:
|
||||
- vfsutil
|
||||
- name: github.com/shurcooL/vfsgen
|
||||
version: bb654eaf43db9a91d1d3201dbd8c4b0423a96872
|
||||
- name: github.com/urfave/cli
|
||||
version: 75104e932ac2ddb944a6ea19d9f9f26316ff1145
|
||||
- name: golang.org/x/net
|
||||
version: 5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec
|
||||
subpackages:
|
||||
- html
|
||||
- html/atom
|
||||
testImports:
|
||||
- name: github.com/gopherjs/gopherjs
|
||||
version: 444abdf920945de5d4a977b572bcc6c674d1e4eb
|
||||
subpackages:
|
||||
- js
|
||||
- name: github.com/jtolds/gls
|
||||
version: 77f18212c9c7edc9bd6a33d383a7b545ce62f064
|
||||
- name: github.com/smartystreets/assertions
|
||||
version: 0b37b35ec7434b77e77a4bb29b79677cced992ea
|
||||
subpackages:
|
||||
- internal/go-render/render
|
||||
- internal/oglematchers
|
||||
- name: github.com/smartystreets/goconvey
|
||||
version: e5b2b7c9111590d019a696c7800593f666e1a7f4
|
||||
subpackages:
|
||||
- convey
|
||||
- convey/gotest
|
||||
- convey/reporting
|
@ -0,0 +1,152 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
log "github.com/qiniu/log"
|
||||
)
|
||||
|
||||
type Bool struct {
|
||||
c Int64
|
||||
}
|
||||
|
||||
func (b *Bool) Get() bool {
|
||||
return b.c.Get() != 0
|
||||
}
|
||||
|
||||
func (b *Bool) toInt64(v bool) int64 {
|
||||
if v {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bool) Set(v bool) {
|
||||
b.c.Set(b.toInt64(v))
|
||||
}
|
||||
|
||||
func (b *Bool) CompareAndSwap(o, n bool) bool {
|
||||
return b.c.CompareAndSwap(b.toInt64(o), b.toInt64(n))
|
||||
}
|
||||
|
||||
func (b *Bool) Swap(v bool) bool {
|
||||
return b.c.Swap(b.toInt64(v)) != 0
|
||||
}
|
||||
|
||||
var bufferPool *BufferPool
|
||||
|
||||
func init() {
|
||||
// 4000行日志缓存
|
||||
bufferPool = NewBufferPool(4000)
|
||||
}
|
||||
|
||||
type MergeWriter struct {
|
||||
lines chan *bytes.Buffer
|
||||
writer io.Writer
|
||||
closed Bool
|
||||
}
|
||||
|
||||
func NewMergeWriter(writer io.Writer) *MergeWriter {
|
||||
merger := &MergeWriter{
|
||||
lines: make(chan *bytes.Buffer, 1000),
|
||||
writer: writer,
|
||||
}
|
||||
merger.closed.Set(false)
|
||||
merger.drainLines()
|
||||
return merger
|
||||
}
|
||||
|
||||
func (m *MergeWriter) Close() {
|
||||
// log.Printf("Close MergeWriter")
|
||||
if m.closed.CompareAndSwap(false, true) {
|
||||
// log.Printf("Close lines chan")
|
||||
close(m.lines)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MergeWriter) WriteStrLine(line string) {
|
||||
if m.closed.Get() {
|
||||
return
|
||||
} else {
|
||||
buffer := bufferPool.Get()
|
||||
buffer.WriteString(line)
|
||||
m.lines <- buffer
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MergeWriter) WriteLine(line *bytes.Buffer) {
|
||||
if m.closed.Get() {
|
||||
// 需要回收Buffer
|
||||
// log.Printf("Write to closed MergeWrite...")
|
||||
bufferPool.Put(line)
|
||||
return
|
||||
} else {
|
||||
m.lines <- line
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MergeWriter) drainLines() {
|
||||
go func() {
|
||||
for line := range m.lines {
|
||||
m.writer.Write(line.Bytes())
|
||||
// 回收
|
||||
bufferPool.Put(line)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 创建新的BufferWriter
|
||||
func (m *MergeWriter) NewWriter(index int) io.Writer {
|
||||
writer := &BufferWriter{
|
||||
merge: m,
|
||||
prefix: fmt.Sprintf(" [P%02d] ", index),
|
||||
}
|
||||
|
||||
// 分配
|
||||
writer.Buffer = bufferPool.Get()
|
||||
writer.Buffer.WriteString(writer.prefix)
|
||||
return writer
|
||||
}
|
||||
|
||||
type BufferWriter struct {
|
||||
Buffer *bytes.Buffer
|
||||
prefix string
|
||||
merge *MergeWriter
|
||||
}
|
||||
|
||||
func (b *BufferWriter) Write(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
|
||||
for len(p) > 0 {
|
||||
index := bytes.IndexByte(p, '\n')
|
||||
if index != -1 {
|
||||
// 写完完整的一行
|
||||
_, err = b.Buffer.Write(p[0 : index+1])
|
||||
if err != nil {
|
||||
log.Error(err, "Writer Buffer failed")
|
||||
return n, err
|
||||
}
|
||||
|
||||
// 将buffer转移到merge中
|
||||
b.merge.WriteLine(b.Buffer)
|
||||
|
||||
// 分配:写入新数据
|
||||
b.Buffer = bufferPool.Get()
|
||||
b.Buffer.WriteString(time.Now().Format("15:04:05") + b.prefix)
|
||||
p = p[index+1:]
|
||||
} else {
|
||||
// 剩下不足一行,一口气全部写入
|
||||
_, err = b.Buffer.Write(p)
|
||||
if err != nil {
|
||||
log.Error(err, "Writer Buffer failed")
|
||||
return n, err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
Loading…
Reference in new issue