diff --git a/src/internal/config/config.go b/src/internal/config/config.go index 1da436f97..068181306 100644 --- a/src/internal/config/config.go +++ b/src/internal/config/config.go @@ -91,11 +91,23 @@ type Config struct { NonUnknownList []string // 非未知来源更新list文件 OtherSourceList []string // 其他类型更新list文件路径 - DownloadSpeedLimitConfig string - LocalDownloadSpeedLimitConfig string - lastoreDaemonStatus LastoreDaemonStatus - UpdateStatus string - PlatformUpdate bool + DownloadSpeedLimitConfig string // 下载限速配置 + LocalDownloadSpeedLimitConfig string + DeliveryRemoteDownloadGlobalLimit string + DeliveryRemoteUploadGlobalLimit string + DeliveryRemoteDownloadPeakLimit string + DeliveryRemoteUploadPeakLimit string + DeliveryRemoteDownloadOffPeakLimit string + DeliveryRemoteUploadOffPeakLimit string + DeliveryLocalDownloadGlobalLimit string + DeliveryLocalUploadGlobalLimit string + DeliveryLocalDownloadPeakLimit string + DeliveryLocalUploadPeakLimit string + DeliveryLocalDownloadOffPeakLimit string + DeliveryLocalUploadOffPeakLimit string + lastoreDaemonStatus LastoreDaemonStatus + UpdateStatus string + PlatformUpdate bool PlatformUrl string // 更新接口地址 StartCheckRange []int // 开机检查更新区间 @@ -213,6 +225,18 @@ const ( dSettingsKeyIntranetUpdate = "intranet-update" dSettingsKeyGetHardwareIdByHelper = "hardware-id-from-helper" dSettingsKeyCheckPolicyInterval = "check-policy-interval" + dSettingsKeyDeliveryRemoteDownloadGlobalLimit = "delivery-remote-download-global-limit" + dSettingsKeyDeliveryRemoteUploadGlobalLimit = "delivery-remote-upload-global-limit" + dSettingsKeyDeliveryRemoteDownloadPeakLimit = "delivery-remote-download-peak-limit" + dSettingsKeyDeliveryRemoteUploadPeakLimit = "delivery-remote-upload-peak-limit" + dSettingsKeyDeliveryRemoteDownloadOffPeakLimit = "delivery-remote-download-offpeak-limit" + dSettingsKeyDeliveryRemoteUploadOffPeakLimit = "delivery-remote-upload-offpeak-limit" + dSettingsKeyDeliveryLocalDownloadGlobalLimit = "delivery-local-download-global-limit" + dSettingsKeyDeliveryLocalUploadGlobalLimit = "delivery-local-upload-global-limit" + dSettingsKeyDeliveryLocalDownloadPeakLimit = "delivery-local-download-peak-limit" + dSettingsKeyDeliveryLocalUploadPeakLimit = "delivery-local-upload-peak-limit" + dSettingsKeyDeliveryLocalDownloadOffPeakLimit = "delivery-local-download-offpeak-limit" + dSettingsKeyDeliveryLocalUploadOffPeakLimit = "delivery-local-upload-offpeak-limit" ) const configTimeLayout = "2006-01-02T15:04:05.999999999-07:00" @@ -476,6 +500,90 @@ func getConfigFromDSettings() *Config { c.LocalDownloadSpeedLimitConfig = v.Value().(string) } + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryRemoteDownloadGlobalLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryRemoteDownloadGlobalLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryRemoteUploadGlobalLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryRemoteUploadGlobalLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryRemoteDownloadPeakLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryRemoteDownloadPeakLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryRemoteUploadPeakLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryRemoteUploadPeakLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryRemoteDownloadOffPeakLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryRemoteDownloadOffPeakLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryRemoteUploadOffPeakLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryRemoteUploadOffPeakLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalDownloadGlobalLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryLocalDownloadGlobalLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalUploadGlobalLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryLocalUploadGlobalLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalDownloadPeakLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryLocalDownloadPeakLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalUploadPeakLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryLocalUploadPeakLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalDownloadOffPeakLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryLocalDownloadOffPeakLimit = v.Value().(string) + } + + v, err = c.dsLastoreManager.Value(0, dSettingsKeyDeliveryLocalUploadOffPeakLimit) + if err != nil { + logger.Warning(err) + } else { + c.DeliveryLocalUploadOffPeakLimit = v.Value().(string) + } + updateLastoreDaemonStatus := func() { v, err = c.dsLastoreManager.Value(0, DSettingsKeyLastoreDaemonStatus) if err != nil { @@ -988,6 +1096,66 @@ func (c *Config) SetLocalDownloadSpeedLimitConfig(config string) error { return c.save(dSettingsKeyLocalDownloadSpeedLimit, config) } +func (c *Config) SetDeliveryRemoteDownloadGlobalLimit(config string) error { + c.DeliveryRemoteDownloadGlobalLimit = config + return c.save(dSettingsKeyDeliveryRemoteDownloadGlobalLimit, config) +} + +func (c *Config) SetDeliveryRemoteUploadGlobalLimit(config string) error { + c.DeliveryRemoteUploadGlobalLimit = config + return c.save(dSettingsKeyDeliveryRemoteUploadGlobalLimit, config) +} + +func (c *Config) SetDeliveryRemoteDownloadPeakLimit(config string) error { + c.DeliveryRemoteDownloadPeakLimit = config + return c.save(dSettingsKeyDeliveryRemoteDownloadPeakLimit, config) +} + +func (c *Config) SetDeliveryRemoteUploadPeakLimit(config string) error { + c.DeliveryRemoteUploadPeakLimit = config + return c.save(dSettingsKeyDeliveryRemoteUploadPeakLimit, config) +} + +func (c *Config) SetDeliveryRemoteDownloadOffPeakLimit(config string) error { + c.DeliveryRemoteDownloadOffPeakLimit = config + return c.save(dSettingsKeyDeliveryRemoteDownloadOffPeakLimit, config) +} + +func (c *Config) SetDeliveryRemoteUploadOffPeakLimit(config string) error { + c.DeliveryRemoteUploadOffPeakLimit = config + return c.save(dSettingsKeyDeliveryRemoteUploadOffPeakLimit, config) +} + +func (c *Config) SetDeliveryLocalDownloadGlobalLimit(config string) error { + c.DeliveryLocalDownloadGlobalLimit = config + return c.save(dSettingsKeyDeliveryLocalDownloadGlobalLimit, config) +} + +func (c *Config) SetDeliveryLocalUploadGlobalLimit(config string) error { + c.DeliveryLocalUploadGlobalLimit = config + return c.save(dSettingsKeyDeliveryLocalUploadGlobalLimit, config) +} + +func (c *Config) SetDeliveryLocalDownloadPeakLimit(config string) error { + c.DeliveryLocalDownloadPeakLimit = config + return c.save(dSettingsKeyDeliveryLocalDownloadPeakLimit, config) +} + +func (c *Config) SetDeliveryLocalUploadPeakLimit(config string) error { + c.DeliveryLocalUploadPeakLimit = config + return c.save(dSettingsKeyDeliveryLocalUploadPeakLimit, config) +} + +func (c *Config) SetDeliveryLocalDownloadOffPeakLimit(config string) error { + c.DeliveryLocalDownloadOffPeakLimit = config + return c.save(dSettingsKeyDeliveryLocalDownloadOffPeakLimit, config) +} + +func (c *Config) SetDeliveryLocalUploadOffPeakLimit(config string) error { + c.DeliveryLocalUploadOffPeakLimit = config + return c.save(dSettingsKeyDeliveryLocalUploadOffPeakLimit, config) +} + func (c *Config) SetLastoreDaemonStatus(status LastoreDaemonStatus) error { c.statusMu.Lock() c.lastoreDaemonStatus = status diff --git a/src/internal/ratelimit/ratelimit.go b/src/internal/ratelimit/ratelimit.go new file mode 100644 index 000000000..4a7cd8f49 --- /dev/null +++ b/src/internal/ratelimit/ratelimit.go @@ -0,0 +1,232 @@ +package ratelimit + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/godbus/dbus/v5" + "github.com/linuxdeepin/go-lib/log" +) + +var logger = log.NewLogger("lastore/rateLimit") + +const UPGRADE_DELIVERY_SERVICE = "org.deepin.upgradedelivery" +const UPGRADE_DELIVERY_OBJECT_PATH = "/org/deepin/upgradedelivery" +const UPGRADE_DELIVERY_INTERFACE = "org.deepin.upgradedelivery" + +// SyncLimit 服务器端限速配置信息 +type SyncLimit struct { + AllDayRateLimit *RateLimitWithTime `json:"a,omitempty"` // 全天限制 + FreeTimeRateLimit *RateLimitWithTime `json:"f,omitempty"` // 闲时限制 + BusyTimeRateLimit *RateLimitWithTime `json:"b,omitempty"` // 忙时限制 +} + +// RateLimitWithTime 时间区间限速 +type RateLimitWithTime struct { + StartTime string `json:"s,omitempty"` // 限制开始时间,format 22:00:00 + EndTime string `json:"e,omitempty"` // 限制结束时间 + RateLimit int `json:"r,omitempty"` // 最大下载速率 (单位: kb/s) + Type int `json:"t,omitempty"` // 忙闲,1:选择,2:不选择 +} + +// IPFSConfig 远程服务器端配置文件信息 +type IPFSConfig struct { + ID string `json:"id"` // 配置文件ID + DownloadLimit *SyncLimit `json:"dl"` // 下载限速 + UploadLimit *SyncLimit `json:"ul"` // 上传限速 +} + +const MaxRate = 1024 * 1024 * 100 // 最大速率(100 MB/s) +const MinRate = 1024 * 1024 // 最小速率(1 MB/s) + +const ( + RateLimitTypeNo = 0 // 表示不设置 + RateLimitTypeLocal = 1 // 本地设置限速 + RateLimitTypeRemote = 2 // 远程设置限速(服务器下发策略) +) + +type RateInfo struct { + LimitType int // 限速类型(CLimitTypeNo,CLimitTypeLocal,CLimitTypeRemote) + StartTime time.Time // 限速开始时间 + EndTime time.Time // 限速结束时间 + LimitRate int64 // 限制速率(不限速前设置的速率值) + CurrentRate int64 // 当前限制速率(实际限速速率:限速时,两者一致,不限速时,CurrentRate为最大限速速率) +} + +type RateInfoEvent struct { + RateInfo // 生效速率信息 + RateType int // 类型(gloabl、busy、free) + Speed int64 // 速度 +} + +type IPFSLimitRate struct { + GlobalLimitRemote *RateInfo // 全局限速(服务器) + GlobalLimitLocal *RateInfo // 全局限速(本地) + BusyLimitRemote *RateInfo // 忙时限速(服务器) + BusyLimitLocal *RateInfo // 忙时限速(本地) + FreeLimitRemote *RateInfo // 空闲限速(服务器) + FreeLimitLocal *RateInfo // 空闲限速(本地) +} + +func SetIPFSRateLimit(uploadLimitRate, downloadLimitRate IPFSLimitRate) error { + ipfsUploadConfigData, err := json.Marshal(uploadLimitRate) + if err != nil { + return fmt.Errorf("failed to marshal upload limit rate: %w", err) + } + ipfsDownloadConfigData, err := json.Marshal(downloadLimitRate) + if err != nil { + return fmt.Errorf("failed to marshal download limit rate: %w", err) + } + logger.Infof("ipfsUploadConfigData: %s", string(ipfsUploadConfigData)) + logger.Infof("ipfsDownloadConfigData: %s", string(ipfsDownloadConfigData)) + sysBus, err := dbus.SystemBus() + if err != nil { + return fmt.Errorf("failed to connect to system bus: %w", err) + } + object := sysBus.Object(UPGRADE_DELIVERY_SERVICE, UPGRADE_DELIVERY_OBJECT_PATH) + if err := object.Call(UPGRADE_DELIVERY_INTERFACE+".SetRateLimit", 0, string(ipfsUploadConfigData), string(ipfsDownloadConfigData)).Store(); err != nil { + return fmt.Errorf("failed to set rate limit: %w", err) + } + return nil +} + +// SetIPFSDownloadRateLimit sets the download rate limit for IPFS. rate is in kilobits per second (kb/s). +func SetIPFSDownloadRateLimit(rate int) error { + sysBus, err := dbus.SystemBus() + if err != nil { + return fmt.Errorf("failed to connect to system bus: %w", err) + } + object := sysBus.Object(UPGRADE_DELIVERY_SERVICE, UPGRADE_DELIVERY_OBJECT_PATH) + if err := object.Call(UPGRADE_DELIVERY_INTERFACE+".SetDownloadRateLimit", 0, rate).Store(); err != nil { + return fmt.Errorf("failed to set download rate limit: %w", err) + } + return nil +} + +// SetIPFSUploadRateLimit sets the upload rate limit for IPFS. rate is in kilobits per second (kb/s). +func SetIPFSUploadRateLimit(rate int) error { + sysBus, err := dbus.SystemBus() + if err != nil { + return fmt.Errorf("failed to connect to system bus: %w", err) + } + object := sysBus.Object(UPGRADE_DELIVERY_SERVICE, UPGRADE_DELIVERY_OBJECT_PATH) + if err := object.Call(UPGRADE_DELIVERY_INTERFACE+".SetUploadRateLimit", 0, rate).Store(); err != nil { + return fmt.Errorf("failed to set upload rate limit: %w", err) + } + return nil +} + +func GetDeliveryUploadRateLimit() (RateInfoEvent, error) { + return getDeliveryRateLimit("UploadLimitSpeed") +} + +func GetDeliveryDownloadRateLimit() (RateInfoEvent, error) { + return getDeliveryRateLimit("DownloadLimitSpeed") +} + +func getDeliveryRateLimit(method string) (RateInfoEvent, error) { + sysBus, err := dbus.SystemBus() + if err != nil { + return RateInfoEvent{}, fmt.Errorf("failed to get delivery rate limit: %w", err) + } + object := sysBus.Object(UPGRADE_DELIVERY_SERVICE, UPGRADE_DELIVERY_OBJECT_PATH) + limitSpeedData, err := object.GetProperty(UPGRADE_DELIVERY_INTERFACE + "." + method) + if err != nil { + return RateInfoEvent{}, fmt.Errorf("failed to get limit speed: %w", err) + } + + var rateInfo RateInfoEvent + limitSpeed := limitSpeedData.Value().(string) + if limitSpeed == "" { + return RateInfoEvent{}, fmt.Errorf("limit speed is empty") + } + if err := json.Unmarshal([]byte(limitSpeed), &rateInfo); err != nil { + return RateInfoEvent{}, fmt.Errorf("failed to unmarshal limit speed: %w", err) + } + return rateInfo, nil +} + +func GetIPFSLimitRateBySyncLimit(syncLimit SyncLimit) (IPFSLimitRate, error) { + var limitRate IPFSLimitRate + if syncLimit.AllDayRateLimit != nil { + rateInfo := convertRateLimitWithTimeToRateInfo(syncLimit.AllDayRateLimit) + if rateInfo != nil { + limitRate.GlobalLimitRemote = rateInfo + } + } + if syncLimit.BusyTimeRateLimit != nil && syncLimit.BusyTimeRateLimit.Type == 1 { + rateInfo := convertRateLimitWithTimeToRateInfo(syncLimit.BusyTimeRateLimit) + if rateInfo != nil { + limitRate.BusyLimitRemote = rateInfo + } + } + if syncLimit.FreeTimeRateLimit != nil && syncLimit.FreeTimeRateLimit.Type == 1 { + rateInfo := convertRateLimitWithTimeToRateInfo(syncLimit.FreeTimeRateLimit) + if rateInfo != nil { + limitRate.FreeLimitRemote = rateInfo + } + } + return limitRate, nil +} + +func convertRateLimitWithTimeToRateInfo(rlwt *RateLimitWithTime) *RateInfo { + if rlwt == nil { + return nil + } + var rateInfo RateInfo + if rlwt.Type == 1 { + rateInfo.LimitType = RateLimitTypeRemote + rateInfo.LimitRate = int64(rlwt.RateLimit) * 1024 // kb ---> byte + rateInfo.CurrentRate = int64(rlwt.RateLimit) * 1024 // kb ---> byte + } else { + rateInfo.LimitType = RateLimitTypeNo + rateInfo.LimitRate = MaxRate + rateInfo.CurrentRate = MaxRate + } + + if rlwt.StartTime != "" { + startTime, err := time.Parse("15:04:05", rlwt.StartTime) + if err == nil { + rateInfo.StartTime = startTime + } + } + if rlwt.EndTime != "" { + endTime, err := time.Parse("15:04:05", rlwt.EndTime) + if err == nil { + rateInfo.EndTime = endTime + } + } + return &rateInfo +} + +type LocalRateLimitConfig struct { + Global *RateInfo + Busy *RateInfo + Free *RateInfo +} + +func GetLocalRateLimitFromConfig(globalLimit, peakLimit, offPeakLimit string) *LocalRateLimitConfig { + var config LocalRateLimitConfig + + if globalLimit != "" { + var rateInfo RateInfo + if err := json.Unmarshal([]byte(globalLimit), &rateInfo); err == nil { + config.Global = &rateInfo + } + } + if peakLimit != "" { + var rateInfo RateInfo + if err := json.Unmarshal([]byte(peakLimit), &rateInfo); err == nil { + config.Busy = &rateInfo + } + } + if offPeakLimit != "" { + var rateInfo RateInfo + if err := json.Unmarshal([]byte(offPeakLimit), &rateInfo); err == nil { + config.Free = &rateInfo + } + } + + return &config +} diff --git a/src/internal/updateplatform/message_report.go b/src/internal/updateplatform/message_report.go index 5fb98c113..c66425adb 100644 --- a/src/internal/updateplatform/message_report.go +++ b/src/internal/updateplatform/message_report.go @@ -35,6 +35,7 @@ import ( "github.com/linuxdeepin/go-lib/strv" "github.com/linuxdeepin/go-lib/utils" . "github.com/linuxdeepin/lastore-daemon/src/internal/config" + "github.com/linuxdeepin/lastore-daemon/src/internal/ratelimit" "github.com/linuxdeepin/lastore-daemon/src/internal/system" ) @@ -122,7 +123,8 @@ type UpdatePlatformManager struct { Tp UpdateTp // 更新策略类型:1.非强制更新,2.强制更新/立即更新,3.强制更新/关机或重启时更新,4.强制更新/指定时间更新 UpdateTime time.Time // 更新时间(指定时间更新时的时间) OnlineRateLimit throttlingMessage - UpdateNowForce bool // 立即更新 + IPFSConfig ratelimit.IPFSConfig // ipfs配置 + UpdateNowForce bool // 立即更新 mu sync.Mutex jobPostMsgMap map[string]*UpgradePostMsg @@ -528,6 +530,7 @@ const ( PostProcess PostProcessEvent PostResult + GetIPFSConfig ) type requestContent struct { @@ -576,6 +579,10 @@ var Urls = map[requestType]requestContent{ "/api/v1/update/status", "POST", }, + GetIPFSConfig: { + "/api/v1/ipfs/config", + "GET", + }, } const secret = "DflXyFwTmaoGmbDkVj8uD62XGb01pkJn" @@ -727,6 +734,26 @@ func (m *UpdatePlatformManager) genPostProcessResponse(buf io.Reader, filePath s return client.Do(request) } +func (m *UpdatePlatformManager) genIpfsConfigResponse() (*http.Response, error) { + uri, err := url.Parse(m.requestUrl) + if err != nil { + return nil, fmt.Errorf("failed to parse %v: %w", uri, err) + } + uri = uri.JoinPath(Urls[GetIPFSConfig].path) + + q := uri.Query() + q.Set("id", m.IPFSConfig.ID) + uri.RawQuery = q.Encode() + client := &http.Client{ + Timeout: 40 * time.Second, + } + request, err := http.NewRequest(Urls[GetIPFSConfig].method, uri.String(), nil) + if err != nil { + return nil, fmt.Errorf("%v new request failed: %w", GetIPFSConfig.string(), err) + } + return client.Do(request) +} + func getResponseData(response *http.Response, reqType requestType) (json.RawMessage, error) { if http.StatusOK == response.StatusCode { respData, err := io.ReadAll(response.Body) @@ -816,6 +843,16 @@ func getCVEData(data json.RawMessage) *CVEMeta { return tmp } +// LoadConfig 加载服务器端配置 +func getIPFSConfigData(data json.RawMessage) *ratelimit.IPFSConfig { + tmp := &ratelimit.IPFSConfig{} + if err := json.Unmarshal(data, &tmp); err != nil { + logger.Warningf("%v failed to Unmarshal msg.Data to IPFSConfig: %v", GetIPFSConfig.string(), err) + return tmp + } + return tmp +} + type UpdateTp int const ( @@ -952,6 +989,30 @@ func (m *UpdatePlatformManager) GenThrottlingByToken() error { return err } +func (m *UpdatePlatformManager) GenIpfsConfig() error { + response, err := m.genIpfsConfigResponse() + if err != nil { + return fmt.Errorf("failed to get ipfs config: %w", err) + } + data, err := getResponseData(response, GetIPFSConfig) + if err != nil { + return fmt.Errorf("failed to get ipfs config data: %w", err) + } + msg := getIPFSConfigData(data) + if msg == nil { + return fmt.Errorf("failed to get ipfs config data") + } + + m.IPFSConfig = *msg + + configData, err := json.Marshal(m.IPFSConfig) + if err != nil { + return fmt.Errorf("failed to marshal ipfs config: %w", err) + } + logger.Infof("ipfs config: %s", string(configData)) + return nil +} + type packageLists struct { Core []system.PlatformPackageInfo `json:"core"` // "必须安装软件包清单" Select []system.PlatformPackageInfo `json:"select"` // "可选软件包清单" @@ -1957,3 +2018,167 @@ func getTaskId() int { func (m *UpdatePlatformManager) UpdateRequestUrl(url string) { m.requestUrl = url } + +func (m *UpdatePlatformManager) UpdateDeliverySpeedLimit() error { + if err := m.GenIpfsConfig(); err != nil { + return fmt.Errorf("failed to gen ipfs config: %w", err) + } + + if m.IPFSConfig.UploadLimit == nil || m.IPFSConfig.DownloadLimit == nil { + return nil + } + + uploadLimitRate, err := ratelimit.GetIPFSLimitRateBySyncLimit(*m.IPFSConfig.UploadLimit) + if err != nil { + return fmt.Errorf("failed to get upload limit rate: %w", err) + } + downloadLimitRate, err := ratelimit.GetIPFSLimitRateBySyncLimit(*m.IPFSConfig.DownloadLimit) + if err != nil { + return fmt.Errorf("failed to get download limit rate: %w", err) + } + + localUploadRateLimit := ratelimit.GetLocalRateLimitFromConfig(m.config.DeliveryLocalUploadGlobalLimit, m.config.DeliveryLocalUploadPeakLimit, m.config.DeliveryLocalUploadOffPeakLimit) + localDownloadRateLimit := ratelimit.GetLocalRateLimitFromConfig(m.config.DeliveryLocalDownloadGlobalLimit, m.config.DeliveryLocalDownloadPeakLimit, m.config.DeliveryLocalDownloadOffPeakLimit) + if localDownloadRateLimit.Global == nil { + localDownloadRateLimit.Global = &ratelimit.RateInfo{ // 本地不限速 + LimitType: ratelimit.RateLimitTypeNo, + LimitRate: int64(ratelimit.MaxRate), + CurrentRate: int64(ratelimit.MaxRate), + } + } + if localUploadRateLimit.Global == nil { + localUploadRateLimit.Global = &ratelimit.RateInfo{ // 本地不限速 + LimitType: ratelimit.RateLimitTypeNo, + LimitRate: int64(ratelimit.MaxRate), + CurrentRate: int64(ratelimit.MaxRate), + } + } + + loggerUpload, err := json.Marshal(localUploadRateLimit) + if err != nil { + return fmt.Errorf("failed to marshal upload rate limit: %w", err) + } + logger.Infof("upload rate limit: %s", string(loggerUpload)) + loggerDownload, err := json.Marshal(localDownloadRateLimit) + if err != nil { + return fmt.Errorf("failed to marshal download rate limit: %w", err) + } + logger.Infof("download rate limit: %s", string(loggerDownload)) + + if localDownloadRateLimit != nil { + downloadLimitRate.GlobalLimitLocal = localDownloadRateLimit.Global + downloadLimitRate.BusyLimitLocal = localDownloadRateLimit.Busy + downloadLimitRate.FreeLimitLocal = localDownloadRateLimit.Free + } + if localUploadRateLimit != nil { + uploadLimitRate.GlobalLimitLocal = localUploadRateLimit.Global + uploadLimitRate.BusyLimitLocal = localUploadRateLimit.Busy + uploadLimitRate.FreeLimitLocal = localUploadRateLimit.Free + } + + if err := ratelimit.SetIPFSRateLimit(uploadLimitRate, downloadLimitRate); err != nil { + return fmt.Errorf("failed to set ipfs rate limit: %w", err) + } + + if uploadLimitRate.GlobalLimitRemote != nil { + remoteUploadGlobalData, err := json.Marshal(uploadLimitRate.GlobalLimitRemote) + if err == nil { + if err := m.config.SetDeliveryRemoteUploadGlobalLimit(string(remoteUploadGlobalData)); err != nil { + logger.Warning(err) + } + } + } + if uploadLimitRate.BusyLimitRemote != nil { + remoteUploadPeakData, err := json.Marshal(uploadLimitRate.BusyLimitRemote) + if err == nil { + if err := m.config.SetDeliveryRemoteUploadPeakLimit(string(remoteUploadPeakData)); err != nil { + logger.Warning(err) + } + } + } + if uploadLimitRate.FreeLimitRemote != nil { + remoteUploadOffPeakData, err := json.Marshal(uploadLimitRate.FreeLimitRemote) + if err == nil { + if err := m.config.SetDeliveryRemoteUploadOffPeakLimit(string(remoteUploadOffPeakData)); err != nil { + logger.Warning(err) + } + } + } + + if downloadLimitRate.GlobalLimitRemote != nil { + remoteDownloadGlobalData, err := json.Marshal(downloadLimitRate.GlobalLimitRemote) + if err == nil { + if err := m.config.SetDeliveryRemoteDownloadGlobalLimit(string(remoteDownloadGlobalData)); err != nil { + logger.Warning(err) + } + } + } + if downloadLimitRate.BusyLimitRemote != nil { + remoteDownloadPeakData, err := json.Marshal(downloadLimitRate.BusyLimitRemote) + if err == nil { + if err := m.config.SetDeliveryRemoteDownloadPeakLimit(string(remoteDownloadPeakData)); err != nil { + logger.Warning(err) + } + } + } + if downloadLimitRate.FreeLimitRemote != nil { + remoteDownloadOffPeakData, err := json.Marshal(downloadLimitRate.FreeLimitRemote) + if err == nil { + if err := m.config.SetDeliveryRemoteDownloadOffPeakLimit(string(remoteDownloadOffPeakData)); err != nil { + logger.Warning(err) + } + } + } + + if uploadLimitRate.GlobalLimitLocal != nil { + localUploadGlobalData, err := json.Marshal(uploadLimitRate.GlobalLimitLocal) + if err == nil { + if err := m.config.SetDeliveryLocalUploadGlobalLimit(string(localUploadGlobalData)); err != nil { + logger.Warning(err) + } + } + } + if uploadLimitRate.BusyLimitLocal != nil { + localUploadPeakData, err := json.Marshal(uploadLimitRate.BusyLimitLocal) + if err == nil { + if err := m.config.SetDeliveryLocalUploadPeakLimit(string(localUploadPeakData)); err != nil { + logger.Warning(err) + } + } + } + if uploadLimitRate.FreeLimitLocal != nil { + localUploadOffPeakData, err := json.Marshal(uploadLimitRate.FreeLimitLocal) + if err == nil { + if err := m.config.SetDeliveryLocalUploadOffPeakLimit(string(localUploadOffPeakData)); err != nil { + logger.Warning(err) + } + } + } + + if downloadLimitRate.GlobalLimitLocal != nil { + localDownloadGlobalData, err := json.Marshal(downloadLimitRate.GlobalLimitLocal) + if err == nil { + if err := m.config.SetDeliveryLocalDownloadGlobalLimit(string(localDownloadGlobalData)); err != nil { + logger.Warning(err) + } + } + } + if downloadLimitRate.BusyLimitLocal != nil { + localDownloadPeakData, err := json.Marshal(downloadLimitRate.BusyLimitLocal) + if err == nil { + if err := m.config.SetDeliveryLocalDownloadPeakLimit(string(localDownloadPeakData)); err != nil { + logger.Warning(err) + } + } + } + if downloadLimitRate.FreeLimitLocal != nil { + localDownloadOffPeakData, err := json.Marshal(downloadLimitRate.FreeLimitLocal) + if err == nil { + if err := m.config.SetDeliveryLocalDownloadOffPeakLimit(string(localDownloadOffPeakData)); err != nil { + logger.Warning(err) + } + } + } + + return nil +} diff --git a/src/lastore-daemon/exported_methods_auto.go b/src/lastore-daemon/exported_methods_auto.go index 372bfd110..de172a1fc 100644 --- a/src/lastore-daemon/exported_methods_auto.go +++ b/src/lastore-daemon/exported_methods_auto.go @@ -195,6 +195,16 @@ func (v *Updater) GetExportedMethods() dbusutil.ExportedMethods { Fn: v.SetDownloadSpeedLimit, InArgs: []string{"limitConfig"}, }, + { + Name: "SetDeliveryDownloadSpeedLimit", + Fn: v.SetDeliveryDownloadSpeedLimit, + InArgs: []string{"limitConfig"}, + }, + { + Name: "SetDeliveryUploadSpeedLimit", + Fn: v.SetDeliveryUploadSpeedLimit, + InArgs: []string{"limitConfig"}, + }, { Name: "SetIdleDownloadConfig", Fn: v.SetIdleDownloadConfig, diff --git a/src/lastore-daemon/manager_update.go b/src/lastore-daemon/manager_update.go index 25ef85fff..ce21cd886 100644 --- a/src/lastore-daemon/manager_update.go +++ b/src/lastore-daemon/manager_update.go @@ -395,6 +395,10 @@ func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { if err = m.refreshThrottlingFromPlatform(); err != nil { logger.Warning("updatePlatform gen download speed limit failed", err) } + + if err := m.updatePlatform.UpdateDeliverySpeedLimit(); err != nil { + logger.Warningf("failed to update delivery speed limit: %v", err) + } } err = m.updatePlatform.UpdateAllPlatformDataSync() diff --git a/src/lastore-daemon/updater.go b/src/lastore-daemon/updater.go index 7d0269c49..ce909dff8 100644 --- a/src/lastore-daemon/updater.go +++ b/src/lastore-daemon/updater.go @@ -50,6 +50,12 @@ type downloadSpeedLimitConfig struct { IsOnlineSpeedLimit bool } +type speedLimitConfig struct { + SpeedLimitEnabled bool + LimitSpeed string + IsOnlineSpeedLimit bool +} + type Updater struct { manager *Manager service *dbusutil.Service diff --git a/src/lastore-daemon/updater_ifc.go b/src/lastore-daemon/updater_ifc.go index 6f0a560e5..d8729a6b1 100644 --- a/src/lastore-daemon/updater_ifc.go +++ b/src/lastore-daemon/updater_ifc.go @@ -6,12 +6,14 @@ package main import ( "encoding/json" + "strconv" "strings" "time" "github.com/godbus/dbus/v5" "github.com/linuxdeepin/dde-api/polkit" "github.com/linuxdeepin/go-lib/dbusutil" + "github.com/linuxdeepin/lastore-daemon/src/internal/ratelimit" ) func (u *Updater) GetCheckIntervalAndTime() (interval float64, checkTime string, busErr *dbus.Error) { @@ -206,3 +208,73 @@ func (u *Updater) CleanTransmissionFiles(sender dbus.Sender) *dbus.Error { } return nil } + +func (u *Updater) SetDeliveryDownloadSpeedLimit(limitConfig string) *dbus.Error { + var speedLimitConfig speedLimitConfig + if err := json.Unmarshal([]byte(limitConfig), &speedLimitConfig); err != nil { + return dbusutil.ToError(err) + } + + rateLimit := -1 + if speedLimitConfig.SpeedLimitEnabled { + limitRate, err := strconv.ParseInt(speedLimitConfig.LimitSpeed, 10, 64) + if err != nil { + return dbusutil.ToError(err) + } + rateLimit = int(limitRate) + } + + if err := ratelimit.SetIPFSDownloadRateLimit(rateLimit); err != nil { + return dbusutil.ToError(err) + } + + rateInfo := ratelimit.RateInfo{ + LimitType: ratelimit.RateLimitTypeLocal, + LimitRate: int64(rateLimit), + CurrentRate: int64(rateLimit), + } + rateInfoData, err := json.Marshal(rateInfo) + if err != nil { + return dbusutil.ToError(err) + } + if err := u.config.SetDeliveryLocalDownloadGlobalLimit(string(rateInfoData)); err != nil { + return dbusutil.ToError(err) + } + + return nil +} + +func (u *Updater) SetDeliveryUploadSpeedLimit(limitConfig string) *dbus.Error { + var speedLimitConfig speedLimitConfig + if err := json.Unmarshal([]byte(limitConfig), &speedLimitConfig); err != nil { + return dbusutil.ToError(err) + } + + rateLimit := -1 + if speedLimitConfig.SpeedLimitEnabled { + limitRate, err := strconv.ParseInt(speedLimitConfig.LimitSpeed, 10, 64) + if err != nil { + return dbusutil.ToError(err) + } + rateLimit = int(limitRate) + } + + if err := ratelimit.SetIPFSUploadRateLimit(rateLimit); err != nil { + return dbusutil.ToError(err) + } + + rateInfo := ratelimit.RateInfo{ + LimitType: ratelimit.RateLimitTypeLocal, + LimitRate: int64(rateLimit), + CurrentRate: int64(rateLimit), + } + rateInfoData, err := json.Marshal(rateInfo) + if err != nil { + return dbusutil.ToError(err) + } + if err := u.config.SetDeliveryLocalUploadGlobalLimit(string(rateInfoData)); err != nil { + return dbusutil.ToError(err) + } + + return nil +}