github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/experimental/clashapi/trafficontrol/manager.go (about)

     1  package trafficontrol
     2  
     3  import (
     4  	"runtime"
     5  	"time"
     6  
     7  	"github.com/inazumav/sing-box/experimental/clashapi/compatible"
     8  	"github.com/sagernet/sing/common/atomic"
     9  )
    10  
    11  type Manager struct {
    12  	uploadTemp    atomic.Int64
    13  	downloadTemp  atomic.Int64
    14  	uploadBlip    atomic.Int64
    15  	downloadBlip  atomic.Int64
    16  	uploadTotal   atomic.Int64
    17  	downloadTotal atomic.Int64
    18  
    19  	connections compatible.Map[string, tracker]
    20  	ticker      *time.Ticker
    21  	done        chan struct{}
    22  	// process     *process.Process
    23  	memory uint64
    24  }
    25  
    26  func NewManager() *Manager {
    27  	manager := &Manager{
    28  		ticker: time.NewTicker(time.Second),
    29  		done:   make(chan struct{}),
    30  		// process: &process.Process{Pid: int32(os.Getpid())},
    31  	}
    32  	go manager.handle()
    33  	return manager
    34  }
    35  
    36  func (m *Manager) Join(c tracker) {
    37  	m.connections.Store(c.ID(), c)
    38  }
    39  
    40  func (m *Manager) Leave(c tracker) {
    41  	m.connections.Delete(c.ID())
    42  }
    43  
    44  func (m *Manager) PushUploaded(size int64) {
    45  	m.uploadTemp.Add(size)
    46  	m.uploadTotal.Add(size)
    47  }
    48  
    49  func (m *Manager) PushDownloaded(size int64) {
    50  	m.downloadTemp.Add(size)
    51  	m.downloadTotal.Add(size)
    52  }
    53  
    54  func (m *Manager) Now() (up int64, down int64) {
    55  	return m.uploadBlip.Load(), m.downloadBlip.Load()
    56  }
    57  
    58  func (m *Manager) Total() (up int64, down int64) {
    59  	return m.uploadTotal.Load(), m.downloadTotal.Load()
    60  }
    61  
    62  func (m *Manager) Connections() int {
    63  	return m.connections.Len()
    64  }
    65  
    66  func (m *Manager) Snapshot() *Snapshot {
    67  	var connections []tracker
    68  	m.connections.Range(func(_ string, value tracker) bool {
    69  		connections = append(connections, value)
    70  		return true
    71  	})
    72  
    73  	//if memoryInfo, err := m.process.MemoryInfo(); err == nil {
    74  	//	m.memory = memoryInfo.RSS
    75  	//} else {
    76  	var memStats runtime.MemStats
    77  	runtime.ReadMemStats(&memStats)
    78  	m.memory = memStats.StackInuse + memStats.HeapInuse + memStats.HeapIdle - memStats.HeapReleased
    79  
    80  	return &Snapshot{
    81  		UploadTotal:   m.uploadTotal.Load(),
    82  		DownloadTotal: m.downloadTotal.Load(),
    83  		Connections:   connections,
    84  		Memory:        m.memory,
    85  	}
    86  }
    87  
    88  func (m *Manager) ResetStatistic() {
    89  	m.uploadTemp.Store(0)
    90  	m.uploadBlip.Store(0)
    91  	m.uploadTotal.Store(0)
    92  	m.downloadTemp.Store(0)
    93  	m.downloadBlip.Store(0)
    94  	m.downloadTotal.Store(0)
    95  }
    96  
    97  func (m *Manager) handle() {
    98  	var uploadTemp int64
    99  	var downloadTemp int64
   100  	for {
   101  		select {
   102  		case <-m.done:
   103  			return
   104  		case <-m.ticker.C:
   105  		}
   106  		uploadTemp = m.uploadTemp.Swap(0)
   107  		downloadTemp = m.downloadTemp.Swap(0)
   108  		m.uploadBlip.Store(uploadTemp)
   109  		m.downloadBlip.Store(downloadTemp)
   110  	}
   111  }
   112  
   113  func (m *Manager) Close() error {
   114  	m.ticker.Stop()
   115  	close(m.done)
   116  	return nil
   117  }
   118  
   119  type Snapshot struct {
   120  	DownloadTotal int64     `json:"downloadTotal"`
   121  	UploadTotal   int64     `json:"uploadTotal"`
   122  	Connections   []tracker `json:"connections"`
   123  	Memory        uint64    `json:"memory"`
   124  }