go-fastdfs/doc/coverage.html

3918 lines
159 KiB
HTML
Raw Normal View History

2019-02-21 17:14:14 +08:00
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
body {
background: black;
color: rgb(80, 80, 80);
}
body, pre, #legend span {
font-family: Menlo, monospace;
font-weight: bold;
}
#topbar {
background: black;
position: fixed;
top: 0; left: 0; right: 0;
height: 42px;
border-bottom: 1px solid rgb(80, 80, 80);
}
#content {
margin-top: 50px;
}
#nav, #legend {
float: left;
margin-left: 10px;
}
#legend {
margin-top: 12px;
}
#nav {
margin-top: 10px;
}
#legend span {
margin: 0 5px;
}
.cov0 { color: rgb(192, 0, 0) }
.cov1 { color: rgb(128, 128, 128) }
.cov2 { color: rgb(116, 140, 131) }
.cov3 { color: rgb(104, 152, 134) }
.cov4 { color: rgb(92, 164, 137) }
.cov5 { color: rgb(80, 176, 140) }
.cov6 { color: rgb(68, 188, 143) }
.cov7 { color: rgb(56, 200, 146) }
.cov8 { color: rgb(44, 212, 149) }
.cov9 { color: rgb(32, 224, 152) }
.cov10 { color: rgb(20, 236, 155) }
</style>
</head>
<body>
<div id="topbar">
<div id="nav">
<select id="files">
<option value="file0">github.com/sjqzhang/go-fastdfs/fileserver.go (62.0%)</option>
</select>
</div>
<div id="legend">
<span>not tracked</span>
<span class="cov0">not covered</span>
<span class="cov8">covered</span>
</div>
</div>
<div id="content">
<pre class="file" id="file0" style="display: none">package main
import (
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"errors"
"flag"
"fmt"
"github.com/astaxie/beego/httplib"
"github.com/deckarep/golang-set"
"github.com/json-iterator/go"
log "github.com/sjqzhang/seelog"
"github.com/sjqzhang/tusd"
"github.com/sjqzhang/tusd/filestore"
"github.com/syndtr/goleveldb/leveldb"
_ "github.com/eventials/go-tus"
"io"
"io/ioutil"
slog "log"
random "math/rand"
"mime/multipart"
"net"
"net/http"
_ "net/http/pprof"
"net/smtp"
"net/url"
"os"
"os/signal"
"path"
"path/filepath"
"reflect"
"regexp"
"runtime"
"runtime/debug"
"strconv"
"strings"
"sync"
"bytes"
"sync/atomic"
"syscall"
"time"
"unsafe"
)
var staticHandler http.Handler
var json = jsoniter.ConfigCompatibleWithStandardLibrary
var server *Server
var logacc log.LoggerInterface
var FOLDERS = []string{DATA_DIR, STORE_DIR, CONF_DIR}
var CONST_QUEUE_SIZE = 100000
var (
FileName string
ptr unsafe.Pointer
DOCKER_DIR = ""
STORE_DIR = STORE_DIR_NAME
CONF_DIR = CONF_DIR_NAME
LOG_DIR = LOG_DIR_NAME
DATA_DIR = DATA_DIR_NAME
LARGE_DIR_NAME = "haystack"
LARGE_DIR = STORE_DIR + "/haystack"
CONST_LEVELDB_FILE_NAME = DATA_DIR + "/fileserver.db"
CONST_STAT_FILE_NAME = DATA_DIR + "/stat.json"
CONST_CONF_FILE_NAME = CONF_DIR + "/cfg.json"
logConfigStr = `
&lt;seelog type="asynctimer" asyncinterval="1000" minlevel="trace" maxlevel="error"&gt;
&lt;outputs formatid="common"&gt;
&lt;buffered formatid="common" size="1048576" flushperiod="1000"&gt;
&lt;rollingfile type="size" filename="{DOCKER_DIR}log/fileserver.log" maxsize="104857600" maxrolls="10"/&gt;
&lt;/buffered&gt;
&lt;/outputs&gt;
&lt;formats&gt;
&lt;format id="common" format="%Date %Time [%LEV] [%File:%Line] [%Func] %Msg%n" /&gt;
&lt;/formats&gt;
&lt;/seelog&gt;
`
logAccessConfigStr = `
&lt;seelog type="asynctimer" asyncinterval="1000" minlevel="trace" maxlevel="error"&gt;
&lt;outputs formatid="common"&gt;
&lt;buffered formatid="common" size="1048576" flushperiod="1000"&gt;
&lt;rollingfile type="size" filename="{DOCKER_DIR}log/access.log" maxsize="104857600" maxrolls="10"/&gt;
&lt;/buffered&gt;
&lt;/outputs&gt;
&lt;formats&gt;
&lt;format id="common" format="%Date %Time [%LEV] [%File:%Line] [%Func] %Msg%n" /&gt;
&lt;/formats&gt;
&lt;/seelog&gt;
`
)
const (
STORE_DIR_NAME = "files"
LOG_DIR_NAME = "log"
DATA_DIR_NAME = "data"
CONF_DIR_NAME = "conf"
CONST_STAT_FILE_COUNT_KEY = "fileCount"
CONST_BIG_UPLOAD_PATH_SUFFIX = "/big/upload/"
CONST_STAT_FILE_TOTAL_SIZE_KEY = "totalSize"
CONST_Md5_ERROR_FILE_NAME = "errors.md5"
CONST_Md5_QUEUE_FILE_NAME = "queue.md5"
CONST_FILE_Md5_FILE_NAME = "files.md5"
CONST_REMOME_Md5_FILE_NAME = "removes.md5"
CONST_SMALL_FILE_SIZE = 1024 * 1024
CONST_MESSAGE_CLUSTER_IP = "Can only be called by the cluster ip,current ip:%s"
cfgJson = `{
"绑定端号": "端口",
"addr": ":8080",
"PeerID": "集群内唯一,请使用0-9的单字符默认自动生成",
"peer_id": "%s",
"本主机地址": "本机http地址,默认自动生成,必段为内网,自动生成不为内网请自行修改,下同",
"host": "%s",
"集群": "集群列表,注意为了高可用IP必须不能是同一个,同一不会自动备份且不能为127.0.0.1,且必须为内网IP默认自动生成",
"peers": ["%s"],
"组号": "用于区别不同的集群(上传或下载)与support_group_upload配合使用,带在下载路径中",
"group": "group1",
"是否合并小文件": "默认不合并,合并可以解决inode不够用的情况当前对于小于1M文件进行合并",
"enable_merge_small_file": false,
"重试同步失败文件的时间": "单位秒",
"refresh_interval": 1800,
"是否自动重命名": "默认不自动重命名,使用原文件名",
"rename_file": false,
"是否支持web上传,方便调试": "默认支持web上传",
"enable_web_upload": true,
"是否支持非日期路径": "默认支持非日期路径,也即支持自定义路径,需要上传文件时指定path",
"enable_custom_path": true,
"下载域名": "用于外网下载文件的域名,不包含http://",
"download_domain": "",
"场景列表": "当设定后,用户指的场景必项在列表中,默认不做限制",
"scenes": [],
"默认场景": "默认default",
"default_scene": "default",
"是否显示目录": "默认显示,方便调试用,上线时请关闭",
"show_dir": true,
"邮件配置": "",
"mail": {
"user": "abc@163.com",
"password": "abc",
"host": "smtp.163.com:25"
},
"告警接收邮件列表": "接收人数组",
"alram_receivers": [],
"告警接收URL": "方法post,参数:subjet,message",
"alarm_url": "",
"下载是否需带token": "真假",
"download_use_token": false,
"下载token过期时间": "单位秒",
"download_token_expire": 600,
"是否自动修复": "在超过1亿文件时出现性能问题取消此选项请手动按天同步请查看FAQ",
"auto_repair": true,
"文件去重算法md5可能存在冲突默认md5": "sha1|md5",
"file_sum_arithmetic": "md5",
"是否支持按组(集群)管理,主要用途是Nginx支持多集群": "默认不支持,不支持时路径为http://10.1.5.4:8080/action,支持时为http://10.1.5.4:8080/group(配置中的group参数)/action,action为动作名如status,delete,sync等",
"support_group_manage": false,
"管理ip列表": "用于管理集的ip白名单,",
"admin_ips": ["127.0.0.1"]
}
`
)
type Common struct {
}
type Server struct {
ldb *leveldb.DB
util *Common
statMap *CommonMap
sumMap *CommonMap //map[string]mapset.Set
queueToPeers chan FileInfo
queueFromPeers chan FileInfo
lockMap *CommonMap
curDate string
host string
}
type FileInfo struct {
Name string `json:"name"`
ReName string `json:"rename"`
Path string `json:"path"`
Md5 string `json:"md5"`
Size int64 `json:"size"`
Peers []string `json:"peers"`
Scene string `json:"scene"`
TimeStamp int64 `json:"timeStamp"`
OffSet int64 `json:"offset"`
}
type JsonResult struct {
Message string `json:"message"`
Status string `json:"status"`
Data interface{} `json:"data"`
}
type FileResult struct {
Url string `json:"url"`
Md5 string `json:"md5"`
Path string `json:"path"`
Domain string `json:"domain"`
Scene string `json:"scene"`
//Just for Compatibility
Scenes string `json:"scenes"`
Retmsg string `json:"retmsg"`
Retcode int `json:"retcode"`
Src string `json:"src"`
}
type Mail struct {
User string `json:"user"`
Password string `json:"password"`
Host string `json:"host"`
}
type StatDateFileInfo struct {
Date string `json:"date"`
TotalSize int64 `json:"totalSize"`
FileCount int64 `json:"fileCount"`
}
type GloablConfig struct {
Addr string `json:"addr"`
Peers []string `json:"peers"`
Group string `json:"group"`
RenameFile bool `json:"rename_file"`
ShowDir bool `json:"show_dir"`
RefreshInterval int `json:"refresh_interval"`
EnableWebUpload bool `json:"enable_web_upload"`
DownloadDomain string `json:"download_domain"`
EnableCustomPath bool `json:"enable_custom_path"`
Scenes []string `json:"scenes"`
AlramReceivers []string `json:"alram_receivers"`
DefaultScene string `json:"default_scene"`
Mail Mail `json:"mail"`
AlarmUrl string `json:"alarm_url"`
DownloadUseToken bool `json:"download_use_token"`
DownloadTokenExpire int `json:"download_token_expire"`
QueueSize int `json:"queue_size"`
AutoRepair bool `json:"auto_repair"`
Host string `json:"host"`
FileSumArithmetic string `json:"file_sum_arithmetic"`
PeerId string `json:"peer_id"`
SupportGroupManage bool `json:"support_group_manage"`
AdminIps []string `json:"admin_ips"`
EnableMergeSmallFile bool `json:"enable_merge_small_file"`
}
func NewServer() *Server <span class="cov8" title="1">{
var (
ldb *leveldb.DB
server *Server
err error
)
server = &amp;Server{
util: &amp;Common{},
statMap: NewCommonMap(0),
lockMap: NewCommonMap(0),
queueToPeers: make(chan FileInfo, CONST_QUEUE_SIZE),
queueFromPeers: make(chan FileInfo, CONST_QUEUE_SIZE),
sumMap: NewCommonMap(363 * 3),
}
settins := httplib.BeegoHTTPSettings{
UserAgent: "go-fastdfs",
ConnectTimeout: 10 * time.Second,
ReadWriteTimeout: 10 * time.Second,
Gzip: true,
DumpBody: true,
}
httplib.SetDefaultSetting(settins)
server.statMap.Put(CONST_STAT_FILE_COUNT_KEY, int64(0))
server.statMap.Put(CONST_STAT_FILE_TOTAL_SIZE_KEY, int64(0))
server.statMap.Put(server.util.GetToDay()+"_"+CONST_STAT_FILE_COUNT_KEY, int64(0))
server.statMap.Put(server.util.GetToDay()+"_"+CONST_STAT_FILE_TOTAL_SIZE_KEY, int64(0))
server.curDate = server.util.GetToDay()
//o := &amp;opt.Options{
// Filter: filter.NewBloomFilter(160),
//
//}
ldb, err = leveldb.OpenFile(CONST_LEVELDB_FILE_NAME, nil)
if err != nil </span><span class="cov0" title="0">{
fmt.Println(err)
panic(err)</span>
<span class="cov0" title="0">log.Error(err)</span>
}
<span class="cov8" title="1">server.ldb = ldb
return server</span>
}
type CommonMap struct {
sync.Mutex
m map[string]interface{}
}
func NewCommonMap(size int) *CommonMap <span class="cov8" title="1">{
if size &gt; 0 </span><span class="cov8" title="1">{
return &amp;CommonMap{m: make(map[string]interface{}, size)}
}</span><span class="cov8" title="1"> else {
return &amp;CommonMap{m: make(map[string]interface{})}
}</span>
}
func (s *CommonMap) GetValue(k string) (interface{}, bool) <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
v, ok := s.m[k]
return v, ok
}</span>
func (s *CommonMap) Put(k string, v interface{}) <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
s.m[k] = v
}</span>
func (s *CommonMap) LockKey(k string) <span class="cov8" title="1">{
s.Lock()
if v, ok := s.m[k]; ok </span><span class="cov0" title="0">{
s.m[k+"_lock_"] = true
s.Unlock()
v.(*sync.Mutex).Lock()
}</span><span class="cov8" title="1"> else {
s.m[k] = &amp;sync.Mutex{}
v = s.m[k]
s.m[k+"_lock_"] = true
s.Unlock()
v.(*sync.Mutex).Lock()
}</span>
}
func (s *CommonMap) UnLockKey(k string) <span class="cov8" title="1">{
s.Lock()
if v, ok := s.m[k]; ok </span><span class="cov8" title="1">{
v.(*sync.Mutex).Unlock()
s.m[k+"_lock_"] = false
}</span>
<span class="cov8" title="1">s.Unlock()</span>
}
func (s *CommonMap) IsLock(k string) bool <span class="cov8" title="1">{
s.Lock()
if v, ok := s.m[k+"_lock_"]; ok </span><span class="cov0" title="0">{
s.Unlock()
return v.(bool)
}</span>
<span class="cov8" title="1">s.Unlock()
return false</span>
}
func (s *CommonMap) Keys() []string <span class="cov8" title="1">{
s.Lock()
keys := make([]string, len(s.m))
defer s.Unlock()
for k, _ := range s.m </span><span class="cov0" title="0">{
keys = append(keys, k)
}</span>
<span class="cov8" title="1">return keys</span>
}
func (s *CommonMap) Clear() <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
s.m = make(map[string]interface{})
}</span>
func (s *CommonMap) Remove(key string) <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
if _, ok := s.m[key]; ok </span><span class="cov8" title="1">{
delete(s.m, key)
}</span>
}
func (s *CommonMap) AddUniq(key string) <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
if _, ok := s.m[key]; !ok </span><span class="cov8" title="1">{
s.m[key] = nil
}</span>
}
func (s *CommonMap) AddCount(key string, count int) <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
if _v, ok := s.m[key]; ok </span><span class="cov0" title="0">{
v := _v.(int)
v = v + count
s.m[key] = v
}</span><span class="cov8" title="1"> else {
s.m[key] = 1
}</span>
}
func (s *CommonMap) AddCountInt64(key string, count int64) <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
if _v, ok := s.m[key]; ok </span><span class="cov8" title="1">{
v := _v.(int64)
v = v + count
s.m[key] = v
}</span><span class="cov0" title="0"> else {
s.m[key] = count
}</span>
}
func (s *CommonMap) Add(key string) <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
if _v, ok := s.m[key]; ok </span><span class="cov8" title="1">{
v := _v.(int)
v = v + 1
s.m[key] = v
}</span><span class="cov0" title="0"> else {
s.m[key] = 1
}</span>
}
func (s *CommonMap) Zero() <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
for k := range s.m </span><span class="cov8" title="1">{
s.m[k] = 0
}</span>
}
func (s *CommonMap) Contains(i ...interface{}) bool <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
for _, val := range i </span><span class="cov8" title="1">{
if _, ok := s.m[val.(string)]; !ok </span><span class="cov0" title="0">{
return false
}</span>
}
<span class="cov8" title="1">return true</span>
}
func (s *CommonMap) Get() map[string]interface{} <span class="cov8" title="1">{
s.Lock()
defer s.Unlock()
m := make(map[string]interface{})
for k, v := range s.m </span><span class="cov8" title="1">{
m[k] = v
}</span>
<span class="cov8" title="1">return m</span>
}
func Config() *GloablConfig <span class="cov8" title="1">{
return (*GloablConfig)(atomic.LoadPointer(&amp;ptr))
}</span>
func ParseConfig(filePath string) <span class="cov8" title="1">{
var (
data []byte
)
if filePath == "" </span><span class="cov0" title="0">{
data = []byte(strings.TrimSpace(cfgJson))
}</span><span class="cov8" title="1"> else {
file, err := os.Open(filePath)
if err != nil </span><span class="cov0" title="0">{
panic(fmt.Sprintln("open file path:", filePath, "error:", err))</span>
}
<span class="cov8" title="1">defer file.Close()
FileName = filePath
data, err = ioutil.ReadAll(file)
if err != nil </span><span class="cov0" title="0">{
panic(fmt.Sprintln("file path:", filePath, " read all error:", err))</span>
}
}
<span class="cov8" title="1">var c GloablConfig
if err := json.Unmarshal(data, &amp;c); err != nil </span><span class="cov0" title="0">{
panic(fmt.Sprintln("file path:", filePath, "json unmarshal error:", err))</span>
}
<span class="cov8" title="1">log.Info(c)
atomic.StorePointer(&amp;ptr, unsafe.Pointer(&amp;c))
log.Info("config parse success")</span>
}
func (this *Common) GetUUID() string <span class="cov8" title="1">{
b := make([]byte, 48)
if _, err := io.ReadFull(rand.Reader, b); err != nil </span><span class="cov0" title="0">{
return ""
}</span>
<span class="cov8" title="1">id := this.MD5(base64.URLEncoding.EncodeToString(b))
return fmt.Sprintf("%s-%s-%s-%s-%s", id[0:8], id[8:12], id[12:16], id[16:20], id[20:])</span>
}
func (this *Common) CopyFile(src, dst string) (int64, error) <span class="cov0" title="0">{
sourceFileStat, err := os.Stat(src)
if err != nil </span><span class="cov0" title="0">{
return 0, err
}</span>
<span class="cov0" title="0">if !sourceFileStat.Mode().IsRegular() </span><span class="cov0" title="0">{
return 0, fmt.Errorf("%s is not a regular file", src)
}</span>
<span class="cov0" title="0">source, err := os.Open(src)
if err != nil </span><span class="cov0" title="0">{
return 0, err
}</span>
<span class="cov0" title="0">defer source.Close()
destination, err := os.Create(dst)
if err != nil </span><span class="cov0" title="0">{
return 0, err
}</span>
<span class="cov0" title="0">defer destination.Close()
nBytes, err := io.Copy(destination, source)
return nBytes, err</span>
}
func (this *Common) RandInt(min, max int) int <span class="cov8" title="1">{
return func(min, max int) int </span><span class="cov8" title="1">{
r := random.New(random.NewSource(time.Now().UnixNano()))
if min &gt;= max </span><span class="cov0" title="0">{
return max
}</span>
<span class="cov8" title="1">return r.Intn(max-min) + min</span>
}(min, max)
}
func (this *Common) GetToDay() string <span class="cov8" title="1">{
return time.Now().Format("20060102")
}</span>
func (this *Common) UrlEncode(v interface{}) string <span class="cov0" title="0">{
switch v.(type) </span>{
case string:<span class="cov0" title="0">
m := make(map[string]string)
m["name"] = v.(string)
return strings.Replace(this.UrlEncodeFromMap(m), "name=", "", 1)</span>
case map[string]string:<span class="cov0" title="0">
return this.UrlEncodeFromMap(v.(map[string]string))</span>
default:<span class="cov0" title="0">
return fmt.Sprintf("%v", v)</span>
}
}
func (this *Common) UrlEncodeFromMap(m map[string]string) string <span class="cov0" title="0">{
vv := url.Values{}
for k, v := range m </span><span class="cov0" title="0">{
vv.Add(k, v)
}</span>
<span class="cov0" title="0">return vv.Encode()</span>
}
func (this *Common) UrlDecodeToMap(body string) (map[string]string, error) <span class="cov0" title="0">{
var (
err error
m map[string]string
v url.Values
)
m = make(map[string]string)
if v, err = url.ParseQuery(body); err != nil </span><span class="cov0" title="0">{
return m, err
}</span>
<span class="cov0" title="0">for _k, _v := range v </span><span class="cov0" title="0">{
if len(_v) &gt; 0 </span><span class="cov0" title="0">{
m[_k] = _v[0]
}</span>
}
<span class="cov0" title="0">return m, nil</span>
}
func (this *Common) GetDayFromTimeStamp(timeStamp int64) string <span class="cov8" title="1">{
return time.Unix(timeStamp, 0).Format("20060102")
}</span>
func (this *Common) StrToMapSet(str string, sep string) mapset.Set <span class="cov8" title="1">{
result := mapset.NewSet()
for _, v := range strings.Split(str, sep) </span><span class="cov8" title="1">{
result.Add(v)
}</span>
<span class="cov8" title="1">return result</span>
}
func (this *Common) MapSetToStr(set mapset.Set, sep string) string <span class="cov8" title="1">{
var (
ret []string
)
for v := range set.Iter() </span><span class="cov8" title="1">{
ret = append(ret, v.(string))
}</span>
<span class="cov8" title="1">return strings.Join(ret, sep)</span>
}
func (this *Common) GetPulicIP() string <span class="cov8" title="1">{
var (
err error
conn net.Conn
)
if conn, err = net.Dial("udp", "8.8.8.8:80"); err != nil </span><span class="cov0" title="0">{
return "127.0.0.1"
}</span>
<span class="cov8" title="1">defer conn.Close()
localAddr := conn.LocalAddr().String()
idx := strings.LastIndex(localAddr, ":")
return localAddr[0:idx]</span>
}
func (this *Common) MD5(str string) string <span class="cov8" title="1">{
md := md5.New()
md.Write([]byte(str))
return fmt.Sprintf("%x", md.Sum(nil))
}</span>
func (this *Common) GetFileMd5(file *os.File) string <span class="cov8" title="1">{
file.Seek(0, 0)
md5h := md5.New()
io.Copy(md5h, file)
sum := fmt.Sprintf("%x", md5h.Sum(nil))
return sum
}</span>
func (this *Common) GetFileSum(file *os.File, alg string) string <span class="cov8" title="1">{
alg = strings.ToLower(alg)
if alg == "sha1" </span><span class="cov0" title="0">{
return this.GetFileSha1Sum(file)
}</span><span class="cov8" title="1"> else {
return this.GetFileMd5(file)
}</span>
}
func (this *Common) GetFileSumByName(filepath string, alg string) (string, error) <span class="cov8" title="1">{
var (
err error
file *os.File
)
file, err = os.Open(filepath)
if err != nil </span><span class="cov0" title="0">{
return "", err
}</span>
<span class="cov8" title="1">defer file.Close()
alg = strings.ToLower(alg)
if alg == "sha1" </span><span class="cov0" title="0">{
return this.GetFileSha1Sum(file), nil
}</span><span class="cov8" title="1"> else {
return this.GetFileMd5(file), nil
}</span>
}
func (this *Common) GetFileSha1Sum(file *os.File) string <span class="cov0" title="0">{
file.Seek(0, 0)
md5h := sha1.New()
io.Copy(md5h, file)
sum := fmt.Sprintf("%x", md5h.Sum(nil))
return sum
}</span>
func (this *Common) WriteFileByOffSet(filepath string, offset int64, data []byte) (error) <span class="cov8" title="1">{
var (
err error
file *os.File
count int
)
file, err = os.OpenFile(filepath, os.O_CREATE|os.O_RDWR, 0666)
if err != nil </span><span class="cov0" title="0">{
return err
}</span>
<span class="cov8" title="1">defer file.Close()
count, err = file.WriteAt(data, offset)
if err != nil </span><span class="cov0" title="0">{
return err
}</span>
<span class="cov8" title="1">if count != len(data) </span><span class="cov0" title="0">{
return errors.New(fmt.Sprintf("write %s error", filepath))
}</span>
<span class="cov8" title="1">return nil</span>
}
func (this *Common) ReadFileByOffSet(filepath string, offset int64, length int) ([]byte, error) <span class="cov8" title="1">{
var (
err error
file *os.File
result []byte
count int
)
file, err = os.Open(filepath)
if err != nil </span><span class="cov0" title="0">{
return nil, err
}</span>
<span class="cov8" title="1">defer file.Close()
result = make([]byte, length)
count, err = file.ReadAt(result, offset)
if err != nil </span><span class="cov0" title="0">{
return nil, err
}</span>
<span class="cov8" title="1">if count != length </span><span class="cov0" title="0">{
return nil, errors.New("read error")
}</span>
<span class="cov8" title="1">return result, nil</span>
}
func (this *Common) Contains(obj interface{}, arrayobj interface{}) bool <span class="cov8" title="1">{
targetValue := reflect.ValueOf(arrayobj)
switch reflect.TypeOf(arrayobj).Kind() </span>{
case reflect.Slice, reflect.Array:<span class="cov8" title="1">
for i := 0; i &lt; targetValue.Len(); i++ </span><span class="cov8" title="1">{
if targetValue.Index(i).Interface() == obj </span><span class="cov8" title="1">{
return true
}</span>
}
case reflect.Map:<span class="cov0" title="0">
if targetValue.MapIndex(reflect.ValueOf(obj)).IsValid() </span><span class="cov0" title="0">{
return true
}</span>
}
<span class="cov8" title="1">return false</span>
}
func (this *Common) FileExists(fileName string) bool <span class="cov8" title="1">{
_, err := os.Stat(fileName)
return err == nil
}</span>
func (this *Common) WriteFile(path string, data string) bool <span class="cov8" title="1">{
if err := ioutil.WriteFile(path, []byte(data), 0775); err == nil </span><span class="cov8" title="1">{
return true
}</span><span class="cov0" title="0"> else {
return false
}</span>
}
func (this *Common) WriteBinFile(path string, data []byte) bool <span class="cov8" title="1">{
if err := ioutil.WriteFile(path, data, 0775); err == nil </span><span class="cov8" title="1">{
return true
}</span><span class="cov0" title="0"> else {
return false
}</span>
}
func (this *Common) IsExist(filename string) bool <span class="cov8" title="1">{
_, err := os.Stat(filename)
return err == nil || os.IsExist(err)
}</span>
func (this *Common) Match(matcher string, content string) []string <span class="cov8" title="1">{
var result []string
if reg, err := regexp.Compile(matcher); err == nil </span><span class="cov8" title="1">{
result = reg.FindAllString(content, -1)
}</span>
<span class="cov8" title="1">return result</span>
}
func (this *Common) ReadBinFile(path string) ([]byte, error) <span class="cov8" title="1">{
if this.IsExist(path) </span><span class="cov8" title="1">{
fi, err := os.Open(path)
if err != nil </span><span class="cov0" title="0">{
return nil, err
}</span>
<span class="cov8" title="1">defer fi.Close()
return ioutil.ReadAll(fi)</span>
}<span class="cov0" title="0"> else {
return nil, errors.New("not found")
}</span>
}
func (this *Common) RemoveEmptyDir(pathname string) <span class="cov8" title="1">{
defer func() </span><span class="cov8" title="1">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("postFileToPeer")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
<span class="cov8" title="1">handlefunc := func(file_path string, f os.FileInfo, err error) error </span><span class="cov8" title="1">{
if f.IsDir() </span><span class="cov8" title="1">{
files, _ := ioutil.ReadDir(file_path)
if len(files) == 0 &amp;&amp; file_path != pathname </span><span class="cov8" title="1">{
os.Remove(file_path)
}</span>
}
<span class="cov8" title="1">return nil</span>
}
<span class="cov8" title="1">fi, _ := os.Stat(pathname)
if fi.IsDir() </span><span class="cov8" title="1">{
filepath.Walk(pathname, handlefunc)
}</span>
}
func (this *Common) JsonEncodePretty(o interface{}) string <span class="cov8" title="1">{
resp := ""
switch o.(type) </span>{
case map[string]interface{}:<span class="cov8" title="1">
if data, err := json.Marshal(o); err == nil </span><span class="cov8" title="1">{
resp = string(data)
}</span>
case map[string]string:<span class="cov0" title="0">
if data, err := json.Marshal(o); err == nil </span><span class="cov0" title="0">{
resp = string(data)
}</span>
case []interface{}:<span class="cov0" title="0">
if data, err := json.Marshal(o); err == nil </span><span class="cov0" title="0">{
resp = string(data)
}</span>
case []string:<span class="cov0" title="0">
if data, err := json.Marshal(o); err == nil </span><span class="cov0" title="0">{
resp = string(data)
}</span>
case string:<span class="cov0" title="0">
resp = o.(string)</span>
default:<span class="cov8" title="1">
if data, err := json.Marshal(o); err == nil </span><span class="cov8" title="1">{
resp = string(data)
}</span>
}
<span class="cov8" title="1">var v interface{}
if ok := json.Unmarshal([]byte(resp), &amp;v); ok == nil </span><span class="cov8" title="1">{
if buf, ok := json.MarshalIndent(v, "", " "); ok == nil </span><span class="cov8" title="1">{
resp = string(buf)
}</span>
}
<span class="cov8" title="1">return resp</span>
}
func (this *Common) GetClientIp(r *http.Request) string <span class="cov8" title="1">{
client_ip := ""
headers := []string{"X_Forwarded_For", "X-Forwarded-For", "X-Real-Ip",
"X_Real_Ip", "Remote_Addr", "Remote-Addr"}
for _, v := range headers </span><span class="cov8" title="1">{
if _v, ok := r.Header[v]; ok </span><span class="cov0" title="0">{
if len(_v) &gt; 0 </span><span class="cov0" title="0">{
client_ip = _v[0]
break</span>
}
}
}
<span class="cov8" title="1">if client_ip == "" </span><span class="cov8" title="1">{
clients := strings.Split(r.RemoteAddr, ":")
client_ip = clients[0]
}</span>
<span class="cov8" title="1">return client_ip</span>
}
func (this *Server) RepairStat() <span class="cov8" title="1">{
defer func() </span><span class="cov8" title="1">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("RepairStat")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
<span class="cov8" title="1">if this.lockMap.IsLock("RepairStat") </span><span class="cov0" title="0">{
log.Warn("Lock RepairStat")
return
}</span>
<span class="cov8" title="1">this.lockMap.LockKey("RepairStat")
defer this.lockMap.UnLockKey("RepairStat")
this.statMap.Put(CONST_STAT_FILE_COUNT_KEY, int64(0))
this.statMap.Put(CONST_STAT_FILE_TOTAL_SIZE_KEY, int64(0))
handlefunc := func(file_path string, f os.FileInfo, err error) error </span><span class="cov8" title="1">{
var (
files []os.FileInfo
date []string
data []byte
content string
lines []string
count int64
totalSize int64
line string
cols []string
size int64
)
if f.IsDir() </span><span class="cov8" title="1">{
if files, err = ioutil.ReadDir(file_path); err != nil </span><span class="cov0" title="0">{
return err
}</span>
<span class="cov8" title="1">for _, file := range files </span><span class="cov8" title="1">{
count = 0
size = 0
if file.Name() == CONST_FILE_Md5_FILE_NAME </span><span class="cov8" title="1">{
if data, err = ioutil.ReadFile(file_path + "/" + file.Name()); err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov8" title="1">date = this.util.Match("\\d{8}", file_path)
if len(date) &lt; 1 </span><span class="cov0" title="0">{
continue</span>
}
<span class="cov8" title="1">content = string(data)
lines = strings.Split(content, "\n")
count = int64(len(lines))
if count &gt; 1 </span><span class="cov8" title="1">{
count = count - 1
}</span>
<span class="cov8" title="1">count = 0
for _, line = range lines </span><span class="cov8" title="1">{
cols = strings.Split(line, "|")
if len(cols) &gt; 2 </span><span class="cov8" title="1">{
count = count + 1
if size, err = strconv.ParseInt(cols[1], 10, 64); err != nil </span><span class="cov0" title="0">{
size = 0
continue</span>
}
<span class="cov8" title="1">totalSize = totalSize + size</span>
}
}
<span class="cov8" title="1">this.statMap.Put(date[0]+"_"+CONST_STAT_FILE_COUNT_KEY, count)
this.statMap.Put(date[0]+"_"+CONST_STAT_FILE_TOTAL_SIZE_KEY, totalSize)
this.statMap.AddCountInt64(CONST_STAT_FILE_COUNT_KEY, count)
this.statMap.AddCountInt64(CONST_STAT_FILE_TOTAL_SIZE_KEY, totalSize)</span>
}
}
}
<span class="cov8" title="1">return nil</span>
}
<span class="cov8" title="1">filepath.Walk(DATA_DIR, handlefunc)
this.SaveStat()</span>
}
func (this *Server) CheckFileExistByMd5(md5s string, fileInfo *FileInfo) bool <span class="cov8" title="1">{
var (
err error
info *FileInfo
)
if info, err = this.GetFileInfoFromLevelDB(md5s); err != nil </span><span class="cov8" title="1">{
return false
}</span>
<span class="cov0" title="0">if info != nil &amp;&amp; info.Md5 != "" </span><span class="cov0" title="0">{
if fileInfo != nil </span><span class="cov0" title="0">{
if fileInfo.Path != info.Path </span><span class="cov0" title="0">{
return false
}</span>
}
<span class="cov0" title="0">return true</span>
}<span class="cov0" title="0"> else {
return false
}</span>
}
func (this *Server) RepairFileInfoFromFile() <span class="cov0" title="0">{
defer func() </span><span class="cov0" title="0">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("RepairFileInfoFromFile")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
<span class="cov0" title="0">if this.lockMap.IsLock("RepairFileInfoFromFile") </span><span class="cov0" title="0">{
log.Warn("Lock RepairFileInfoFromFile")
return
}</span>
<span class="cov0" title="0">this.lockMap.LockKey("RepairFileInfoFromFile")
defer this.lockMap.UnLockKey("RepairFileInfoFromFile")
handlefunc := func(file_path string, f os.FileInfo, err error) error </span><span class="cov0" title="0">{
var (
files []os.FileInfo
fi os.FileInfo
fileInfo FileInfo
sum string
)
if f.IsDir() </span><span class="cov0" title="0">{
files, err = ioutil.ReadDir(file_path)
if err != nil </span><span class="cov0" title="0">{
return err
}</span>
<span class="cov0" title="0">for _, fi = range files </span><span class="cov0" title="0">{
if fi.IsDir() || fi.Size() == 0 </span><span class="cov0" title="0">{
continue</span>
}
<span class="cov0" title="0">sum, err = this.util.GetFileSumByName(file_path+"/"+fi.Name(), Config().FileSumArithmetic)
if err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov0" title="0">fileInfo = FileInfo{
Size: fi.Size(),
Name: fi.Name(),
Path: strings.Replace(file_path, "\\", "/", -1),
Md5: sum,
TimeStamp: fi.ModTime().Unix(),
}
this.SaveFileMd5Log(&amp;fileInfo, CONST_FILE_Md5_FILE_NAME)</span>
}
}
<span class="cov0" title="0">return nil</span>
}
<span class="cov0" title="0">pathname := STORE_DIR
fi, _ := os.Stat(pathname)
if fi.IsDir() </span><span class="cov0" title="0">{
filepath.Walk(pathname, handlefunc)
}</span>
}
func (this *Server) DownloadFromPeer(peer string, fileInfo *FileInfo) <span class="cov8" title="1">{
var (
err error
filename string
fpath string
fi os.FileInfo
sum string
data []byte
)
if this.CheckFileExistByMd5(fileInfo.Md5, fileInfo) </span><span class="cov0" title="0">{
return
}</span>
<span class="cov8" title="1">if _, err = os.Stat(fileInfo.Path); err != nil </span><span class="cov0" title="0">{
os.MkdirAll(DOCKER_DIR+fileInfo.Path, 0775)
}</span>
<span class="cov8" title="1">filename = fileInfo.Name
if fileInfo.ReName != "" </span><span class="cov8" title="1">{
filename = fileInfo.ReName
}</span>
//fmt.Println("downloadFromPeer",fileInfo)
<span class="cov8" title="1">p := strings.Replace(fileInfo.Path, STORE_DIR_NAME+"/", "", 1)
//filename=this.util.UrlEncode(filename)
req := httplib.Get(peer + "/" + Config().Group + "/" + p + "/" + filename)
fpath = DOCKER_DIR + fileInfo.Path + "/" + filename
timeout := fileInfo.Size/1024/1024/8 + 30
req.SetTimeout(time.Second*5, time.Second*time.Duration(timeout))
if fileInfo.OffSet != -1 </span><span class="cov8" title="1">{ //small file download
data, err = req.Bytes()
if err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">data2 := make([]byte, len(data)+1)
data2[0] = '1'
for i, v := range data </span><span class="cov8" title="1">{
data2[i+1] = v
}</span>
<span class="cov8" title="1">data = data2
if int64(len(data)) != fileInfo.Size </span><span class="cov0" title="0">{
log.Warn("file size is error")
return
}</span>
<span class="cov8" title="1">fpath = strings.Split(fpath, ",")[0]
err = this.util.WriteFileByOffSet(fpath, fileInfo.OffSet, data)
if err != nil </span><span class="cov0" title="0">{
log.Warn(err)
}</span>
<span class="cov8" title="1">this.SaveFileMd5Log(fileInfo, CONST_FILE_Md5_FILE_NAME)
return</span>
}
<span class="cov8" title="1">if err = req.ToFile(fpath); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">if fi, err = os.Stat(fpath); err != nil </span><span class="cov0" title="0">{
os.Remove(fpath)
return
}</span>
<span class="cov8" title="1">if sum, err = this.util.GetFileSumByName(fpath, Config().FileSumArithmetic); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">if fi.Size() != fileInfo.Size || sum != fileInfo.Md5 </span><span class="cov0" title="0">{
log.Error("file sum check error")
os.Remove(fpath)
return
}</span>
<span class="cov8" title="1">if this.util.IsExist(fpath) </span><span class="cov8" title="1">{
this.SaveFileMd5Log(fileInfo, CONST_FILE_Md5_FILE_NAME)
}</span>
}
func (this *Server) Download(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
err error
pathMd5 string
info os.FileInfo
peer string
fileInfo *FileInfo
fullpath string
pathval url.Values
token string
timestamp string
maxTimestamp int64
minTimestamp int64
ts int64
md5sum string
fp *os.File
isPeer bool
isSmallFile bool
data []byte
offset int64
length int
smallPath string
notFound bool
//isBigFile bool
)
r.ParseForm()
isPeer = this.IsPeer(r)
if Config().DownloadUseToken &amp;&amp; !isPeer </span><span class="cov0" title="0">{
token = r.FormValue("token")
timestamp = r.FormValue("timestamp")
if token == "" || timestamp == "" </span><span class="cov0" title="0">{
w.Write([]byte("unvalid request"))
return
}</span>
<span class="cov0" title="0">maxTimestamp = time.Now().Add(time.Second *
time.Duration(Config().DownloadTokenExpire)).Unix()
minTimestamp = time.Now().Add(-time.Second *
time.Duration(Config().DownloadTokenExpire)).Unix()
if ts, err = strconv.ParseInt(timestamp, 10, 64); err != nil </span><span class="cov0" title="0">{
w.Write([]byte("unvalid timestamp"))
return
}</span>
<span class="cov0" title="0">if ts &gt; maxTimestamp || ts &lt; minTimestamp </span><span class="cov0" title="0">{
w.Write([]byte("timestamp expire"))
return
}</span>
}
<span class="cov8" title="1">fullpath = r.RequestURI[len(Config().Group)+2 : len(r.RequestURI)]
fullpath = DOCKER_DIR + STORE_DIR_NAME + "/" + fullpath
//fmt.Println("fullpath",fullpath)
if strings.HasPrefix(r.RequestURI, "/"+Config().Group+"/"+LARGE_DIR_NAME+"/") </span><span class="cov8" title="1">{
isSmallFile = true
smallPath = fullpath //notice order
fullpath = strings.Split(fullpath, ",")[0]
}</span>
<span class="cov8" title="1">_ = isSmallFile
_ = smallPath
fullpath = strings.Replace(fullpath, "&amp;", "$$$$", -1)
if pathval, err = url.ParseQuery(fullpath); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span><span class="cov8" title="1"> else {
for k, v := range pathval </span><span class="cov8" title="1">{
if k != "" </span><span class="cov8" title="1">{
if len(v) &gt; 0 &amp;&amp; v[0] != "" </span><span class="cov0" title="0">{
fullpath = k + "=" + v[0]
}</span><span class="cov8" title="1"> else {
fullpath = k
}</span>
}
}
}
<span class="cov8" title="1">fullpath = strings.Replace(fullpath, "$$$$", "&amp;", -1)
CheckToken := func(token string, md5sum string, timestamp string) bool </span><span class="cov0" title="0">{
if this.util.MD5(md5sum+timestamp) != token </span><span class="cov0" title="0">{
return false
}</span>
<span class="cov0" title="0">return true</span>
}
<span class="cov8" title="1">if Config().DownloadUseToken &amp;&amp; !isPeer </span><span class="cov0" title="0">{
if isSmallFile </span><span class="cov0" title="0">{
pathMd5 = this.util.MD5(smallPath)
}</span><span class="cov0" title="0"> else {
fullpath = strings.Split(fullpath, "?")[0]
pathMd5 = this.util.MD5(fullpath)
}</span>
<span class="cov0" title="0">if fileInfo, err = this.GetFileInfoFromLevelDB(pathMd5); err != nil </span><span class="cov0" title="0">{
log.Error(err)
if this.util.FileExists(fullpath) </span><span class="cov0" title="0">{
if fp, err = os.Create(fullpath); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
<span class="cov0" title="0">if fp != nil </span><span class="cov0" title="0">{
defer fp.Close()
}</span>
<span class="cov0" title="0">md5sum = this.util.GetFileSum(fp, Config().FileSumArithmetic)
if !CheckToken(token, md5sum, timestamp) </span><span class="cov0" title="0">{
w.Write([]byte("unvalid request,error token"))
return
}</span>
}
}<span class="cov0" title="0"> else {
if !CheckToken(token, fileInfo.Md5, timestamp) </span><span class="cov0" title="0">{
w.Write([]byte("unvalid request,error token"))
return
}</span>
}
}
<span class="cov8" title="1">if isSmallFile </span><span class="cov8" title="1">{
pos := strings.Split(r.RequestURI, ",")
if len(pos) &lt; 3 </span><span class="cov0" title="0">{
w.Write([]byte("(error) uri invalid"))
return
}</span>
<span class="cov8" title="1">offset, err = strconv.ParseInt(pos[1], 10, 64)
if err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">if length, err = strconv.Atoi(pos[2]); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">if length &gt; CONST_SMALL_FILE_SIZE || offset &lt; 0 </span><span class="cov0" title="0">{
log.Warn("invalid filesize or offset")
return
}</span>
<span class="cov8" title="1">if info, err = os.Stat(fullpath); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">if info.Size() &lt; offset+int64(length) </span><span class="cov0" title="0">{
notFound = true
}</span><span class="cov8" title="1"> else {
data, err = this.util.ReadFileByOffSet(fullpath, offset, length)
if err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">if string(data[0]) == "1" </span><span class="cov8" title="1">{
w.Write(data[1:])
return
}</span><span class="cov0" title="0"> else {
notFound = true
}</span>
}
}
<span class="cov8" title="1">if info, err = os.Stat(fullpath); err != nil </span><span class="cov0" title="0">{
log.Error(err)
if isSmallFile &amp;&amp; notFound </span><span class="cov0" title="0">{
pathMd5 = this.util.MD5(smallPath)
}</span><span class="cov0" title="0"> else {
pathMd5 = this.util.MD5(fullpath)
}</span>
<span class="cov0" title="0">for _, peer = range Config().Peers </span><span class="cov0" title="0">{
if fileInfo, err = this.checkPeerFileExist(peer, pathMd5); err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov0" title="0">if fileInfo.Md5 != "" </span><span class="cov0" title="0">{
if Config().DownloadUseToken &amp;&amp; !isPeer </span><span class="cov0" title="0">{
if !CheckToken(token, fileInfo.Md5, timestamp) </span><span class="cov0" title="0">{
w.Write([]byte("unvalid request,error token"))
return
}</span>
}
<span class="cov0" title="0">go this.DownloadFromPeer(peer, fileInfo)
http.Redirect(w, r, peer+r.RequestURI, 302)
return</span>
}
}
<span class="cov0" title="0">w.WriteHeader(404)
return</span>
}
<span class="cov8" title="1">if !Config().ShowDir &amp;&amp; info.IsDir() </span><span class="cov0" title="0">{
w.Write([]byte("list dir deny"))
return
}</span>
<span class="cov8" title="1">log.Info("download:" + r.RequestURI)
staticHandler.ServeHTTP(w, r)</span>
}
func (this *Server) GetServerURI(r *http.Request) string <span class="cov0" title="0">{
return fmt.Sprintf("http://%s/", r.Host)
}</span>
func (this *Server) CheckFileAndSendToPeer(date string, filename string, isForceUpload bool) <span class="cov8" title="1">{
var (
md5set mapset.Set
err error
md5s []interface{}
)
defer func() </span><span class="cov8" title="1">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("CheckFileAndSendToPeer")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
<span class="cov8" title="1">if md5set, err = this.GetMd5sByDate(date, filename); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">md5s = md5set.ToSlice()
for _, md := range md5s </span><span class="cov8" title="1">{
if md == nil </span><span class="cov8" title="1">{
continue</span>
}
<span class="cov8" title="1">if fileInfo, _ := this.GetFileInfoFromLevelDB(md.(string)); fileInfo != nil &amp;&amp; fileInfo.Md5 != "" </span><span class="cov8" title="1">{
if isForceUpload </span><span class="cov8" title="1">{
fileInfo.Peers = []string{}
}</span>
<span class="cov8" title="1">if len(fileInfo.Peers) &gt; len(Config().Peers) </span><span class="cov8" title="1">{
continue</span>
}
<span class="cov8" title="1">if !this.util.Contains(this.host, fileInfo.Peers) </span><span class="cov8" title="1">{
fileInfo.Peers = append(fileInfo.Peers, this.host) // peer is null
}</span>
<span class="cov8" title="1">if filename == CONST_Md5_QUEUE_FILE_NAME </span><span class="cov0" title="0">{
this.AppendToDownloadQueue(fileInfo)
}</span><span class="cov8" title="1"> else {
this.AppendToQueue(fileInfo)
}</span>
}
}
}
func (this *Server) postFileToPeer(fileInfo *FileInfo) <span class="cov8" title="1">{
var (
err error
peer string
filename string
info *FileInfo
postURL string
result string
fi os.FileInfo
i int
data []byte
fpath string
)
defer func() </span><span class="cov8" title="1">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("postFileToPeer")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
//fmt.Println("postFile",fileInfo)
<span class="cov8" title="1">for i, peer = range Config().Peers </span><span class="cov8" title="1">{
_ = i
if fileInfo.Peers == nil </span><span class="cov0" title="0">{
fileInfo.Peers = []string{}
}</span>
<span class="cov8" title="1">if this.util.Contains(peer, fileInfo.Peers) </span><span class="cov8" title="1">{
continue</span>
}
<span class="cov8" title="1">filename = fileInfo.Name
if fileInfo.ReName != "" </span><span class="cov8" title="1">{
filename = fileInfo.ReName
if fileInfo.OffSet != -1 </span><span class="cov8" title="1">{
filename = strings.Split(fileInfo.ReName, ",")[0]
}</span>
}
<span class="cov8" title="1">fpath = DOCKER_DIR + fileInfo.Path + "/" + filename
if !this.util.FileExists(fpath) </span><span class="cov0" title="0">{
log.Warn(fmt.Sprintf("file '%s' not found", fpath))
continue</span>
}<span class="cov8" title="1"> else {
if fileInfo.Size == 0 </span><span class="cov0" title="0">{
if fi, err = os.Stat(fpath); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span><span class="cov0" title="0"> else {
fileInfo.Size = fi.Size()
}</span>
}
}
<span class="cov8" title="1">if info, err = this.checkPeerFileExist(peer, fileInfo.Md5); info.Md5 != "" </span><span class="cov8" title="1">{
fileInfo.Peers = append(fileInfo.Peers, peer)
if _, err = this.SaveFileInfoToLevelDB(fileInfo.Md5, fileInfo); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
<span class="cov8" title="1">continue</span>
}
<span class="cov8" title="1">postURL = fmt.Sprintf("%s%s", peer, this.getRequestURI("syncfile_info"))
b := httplib.Post(postURL)
b.SetTimeout(time.Second*5, time.Second*5)
if data, err = json.Marshal(fileInfo); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">b.Param("fileInfo", string(data))
result, err = b.String()
if !strings.HasPrefix(result, "http://") || err != nil </span><span class="cov0" title="0">{
this.SaveFileMd5Log(fileInfo, CONST_Md5_ERROR_FILE_NAME)
}</span>
<span class="cov8" title="1">if strings.HasPrefix(result, "http://") </span><span class="cov8" title="1">{
log.Info(result)
if !this.util.Contains(peer, fileInfo.Peers) </span><span class="cov8" title="1">{
fileInfo.Peers = append(fileInfo.Peers, peer)
if _, err = this.SaveFileInfoToLevelDB(fileInfo.Md5, fileInfo); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
}
}
<span class="cov8" title="1">if err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
}
}
func (this *Server) SaveFileMd5Log(fileInfo *FileInfo, filename string) <span class="cov8" title="1">{
var (
err error
msg string
tmpFile *os.File
logpath string
outname string
logDate string
ok bool
sumKey string
sumset mapset.Set
fullpath string
v interface{}
)
logDate = this.util.GetDayFromTimeStamp(fileInfo.TimeStamp)
sumKey = fmt.Sprintf("%s_%s", logDate, filename)
if v, ok = this.sumMap.GetValue(sumKey); !ok </span><span class="cov8" title="1">{
if sumset, err = this.GetMd5sByDate(logDate, filename); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
<span class="cov8" title="1">if sumset != nil </span><span class="cov8" title="1">{
this.sumMap.Put(sumKey, sumset)
}</span>
}<span class="cov8" title="1"> else {
sumset = v.(mapset.Set)
if sumset.Cardinality() == 0 </span><span class="cov0" title="0">{
sumset, err = this.GetMd5sByDate(logDate, filename)
}</span>
}
<span class="cov8" title="1">if sumset.Contains(fileInfo.Md5) </span><span class="cov0" title="0">{
return
}</span>
<span class="cov8" title="1">outname = fileInfo.Name
if fileInfo.ReName != "" </span><span class="cov8" title="1">{
outname = fileInfo.ReName
}</span>
<span class="cov8" title="1">fullpath = fileInfo.Path + "/" + outname
logpath = DATA_DIR + "/" + time.Unix(fileInfo.TimeStamp, 0).Format("20060102")
if _, err = os.Stat(logpath); err != nil </span><span class="cov0" title="0">{
os.MkdirAll(logpath, 0775)
}</span>
<span class="cov8" title="1">msg = fmt.Sprintf("%s|%d|%d|%s\n", fileInfo.Md5, fileInfo.Size, fileInfo.TimeStamp, fullpath)
if tmpFile, err = os.OpenFile(logpath+"/"+filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">defer tmpFile.Close()
tmpFile.WriteString(msg)
if filename == CONST_FILE_Md5_FILE_NAME </span><span class="cov8" title="1">{
if _, err := this.SaveFileInfoToLevelDB(fileInfo.Md5, fileInfo); err != nil </span><span class="cov0" title="0">{
log.Error("saveToLevelDB", err, fileInfo)
}</span>
<span class="cov8" title="1">if _, err = this.SaveFileInfoToLevelDB(this.util.MD5(fullpath), fileInfo); err != nil </span><span class="cov0" title="0">{
log.Error("saveToLevelDB", err, fileInfo)
}</span>
<span class="cov8" title="1">this.statMap.AddCountInt64(logDate+"_"+CONST_STAT_FILE_COUNT_KEY, 1)
this.statMap.AddCountInt64(logDate+"_"+CONST_STAT_FILE_TOTAL_SIZE_KEY, fileInfo.Size)
this.statMap.AddCountInt64(CONST_STAT_FILE_TOTAL_SIZE_KEY, fileInfo.Size)
this.statMap.AddCountInt64(CONST_STAT_FILE_COUNT_KEY, 1)
this.SaveStat()</span>
}
<span class="cov8" title="1">sumset.Add(fileInfo.Md5)</span>
}
func (this *Server) checkPeerFileExist(peer string, md5sum string) (*FileInfo, error) <span class="cov8" title="1">{
var (
err error
fileInfo FileInfo
)
req := httplib.Post(fmt.Sprintf("%s%s?md5=%s", peer, this.getRequestURI("check_file_exist"), md5sum))
req.SetTimeout(time.Second*5, time.Second*10)
if err = req.ToJSON(&amp;fileInfo); err != nil </span><span class="cov0" title="0">{
return &amp;FileInfo{}, err
}</span>
<span class="cov8" title="1">if fileInfo.Md5 == "" </span><span class="cov8" title="1">{
return &amp;fileInfo, errors.New("not found")
}</span>
<span class="cov8" title="1">return &amp;fileInfo, nil</span>
}
func (this *Server) CheckFileExist(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
data []byte
err error
fileInfo *FileInfo
fpath string
)
r.ParseForm()
md5sum := ""
md5sum = r.FormValue("md5")
if fileInfo, err = this.GetFileInfoFromLevelDB(md5sum); fileInfo != nil </span><span class="cov8" title="1">{
if fileInfo.OffSet != -1 </span><span class="cov8" title="1">{
if data, err = json.Marshal(fileInfo); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
<span class="cov8" title="1">w.Write(data)
return</span>
}
<span class="cov8" title="1">fpath = DOCKER_DIR + fileInfo.Path + "/" + fileInfo.Name
if fileInfo.ReName != "" </span><span class="cov0" title="0">{
fpath = DOCKER_DIR + fileInfo.Path + "/" + fileInfo.ReName
}</span>
<span class="cov8" title="1">if this.util.IsExist(fpath) </span><span class="cov8" title="1">{
if data, err = json.Marshal(fileInfo); err == nil </span><span class="cov8" title="1">{
w.Write(data)
return
}</span><span class="cov0" title="0"> else {
log.Error(err)
}</span>
}<span class="cov0" title="0"> else {
if fileInfo.OffSet == -1 </span><span class="cov0" title="0">{
this.RemoveKeyFromLevelDB(md5sum) // when file delete,delete from leveldb
}</span>
}
}
<span class="cov8" title="1">data, _ = json.Marshal(FileInfo{})
w.Write(data)
return</span>
}
func (this *Server) Sync(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
result JsonResult
)
r.ParseForm()
result.Status = "fail"
if !this.IsPeer(r) </span><span class="cov0" title="0">{
result.Message = "client must be in cluster"
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
<span class="cov8" title="1">date := ""
force := ""
isForceUpload := false
force = r.FormValue("force")
date = r.FormValue("date")
if force == "1" </span><span class="cov8" title="1">{
isForceUpload = true
}</span>
<span class="cov8" title="1">if date == "" </span><span class="cov0" title="0">{
result.Message = "require paramete date &amp;force , ?date=20181230"
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
<span class="cov8" title="1">date = strings.Replace(date, ".", "", -1)
if isForceUpload </span><span class="cov8" title="1">{
go this.CheckFileAndSendToPeer(date, CONST_FILE_Md5_FILE_NAME, isForceUpload)
}</span><span class="cov0" title="0"> else {
go this.CheckFileAndSendToPeer(date, CONST_Md5_ERROR_FILE_NAME, isForceUpload)
}</span>
<span class="cov8" title="1">result.Status = "ok"
result.Message = "job is running"
w.Write([]byte(this.util.JsonEncodePretty(result)))</span>
}
func (this *Server) GetFileInfoFromLevelDB(key string) (*FileInfo, error) <span class="cov8" title="1">{
var (
err error
data []byte
fileInfo FileInfo
)
if data, err = this.ldb.Get([]byte(key), nil); err != nil </span><span class="cov8" title="1">{
return nil, err
}</span>
<span class="cov8" title="1">if err = json.Unmarshal(data, &amp;fileInfo); err != nil </span><span class="cov0" title="0">{
return nil, err
}</span>
<span class="cov8" title="1">return &amp;fileInfo, nil</span>
}
func (this *Server) SaveStat() <span class="cov8" title="1">{
SaveStatFunc := func() </span><span class="cov8" title="1">{
defer func() </span><span class="cov8" title="1">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("SaveStatFunc")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
<span class="cov8" title="1">stat := this.statMap.Get()
if v, ok := stat[CONST_STAT_FILE_COUNT_KEY]; ok </span><span class="cov8" title="1">{
switch v.(type) </span>{
case int64, int32, int, float64, float32:<span class="cov8" title="1">
if v.(int64) &gt;= 0 </span><span class="cov8" title="1">{
if data, err := json.Marshal(stat); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span><span class="cov8" title="1"> else {
this.util.WriteBinFile(CONST_STAT_FILE_NAME, data)
}</span>
}
}
}
}
<span class="cov8" title="1">SaveStatFunc()</span>
}
func (this *Server) RemoveKeyFromLevelDB(key string) (error) <span class="cov0" title="0">{
var (
err error
)
err = this.ldb.Delete([]byte(key), nil)
return err
}</span>
func (this *Server) SaveFileInfoToLevelDB(key string, fileInfo *FileInfo) (*FileInfo, error) <span class="cov8" title="1">{
var (
err error
data []byte
)
if data, err = json.Marshal(fileInfo); err != nil </span><span class="cov0" title="0">{
return fileInfo, err
}</span>
<span class="cov8" title="1">if err = this.ldb.Put([]byte(key), data, nil); err != nil </span><span class="cov0" title="0">{
return fileInfo, err
}</span>
<span class="cov8" title="1">return fileInfo, nil</span>
}
func (this *Server) IsPeer(r *http.Request) bool <span class="cov8" title="1">{
var (
ip string
peer string
bflag bool
)
//return true
ip = this.util.GetClientIp(r)
if ip == "127.0.0.1" || ip == this.util.GetPulicIP() </span><span class="cov8" title="1">{
return true
}</span>
<span class="cov8" title="1">if this.util.Contains(ip, Config().AdminIps) </span><span class="cov0" title="0">{
return true
}</span>
<span class="cov8" title="1">ip = "http://" + ip
bflag = false
for _, peer = range Config().Peers </span><span class="cov8" title="1">{
if strings.HasPrefix(peer, ip) </span><span class="cov8" title="1">{
bflag = true
break</span>
}
}
<span class="cov8" title="1">return bflag</span>
}
func (this *Server) ReceiveMd5s(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
err error
md5str string
fileInfo *FileInfo
md5s []string
)
if !this.IsPeer(r) </span><span class="cov0" title="0">{
log.Warn(fmt.Sprintf("ReceiveMd5s %s", this.util.GetClientIp(r)))
w.Write([]byte(this.GetClusterNotPermitMessage(r)))
return
}</span>
<span class="cov8" title="1">r.ParseForm()
md5str = r.FormValue("md5s")
md5s = strings.Split(md5str, ",")
AppendFunc := func(md5s []string) </span><span class="cov8" title="1">{
for _, m := range md5s </span><span class="cov8" title="1">{
if m != "" </span><span class="cov8" title="1">{
if fileInfo, err = this.GetFileInfoFromLevelDB(m); err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov8" title="1">this.AppendToQueue(fileInfo)</span>
}
}
}
<span class="cov8" title="1">go AppendFunc(md5s)</span>
}
func (this *Server) GetClusterNotPermitMessage(r *http.Request) string <span class="cov0" title="0">{
var (
message string
)
message = fmt.Sprintf(CONST_MESSAGE_CLUSTER_IP, this.util.GetClientIp(r))
return message
}</span>
func (this *Server) GetMd5sForWeb(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
date string
err error
result mapset.Set
lines []string
md5s []interface{}
)
if !this.IsPeer(r) </span><span class="cov0" title="0">{
w.Write([]byte(this.GetClusterNotPermitMessage(r)))
return
}</span>
<span class="cov8" title="1">date = r.FormValue("date")
if result, err = this.GetMd5sByDate(date, CONST_FILE_Md5_FILE_NAME); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
<span class="cov8" title="1">md5s = result.ToSlice()
for _, line := range md5s </span><span class="cov8" title="1">{
if line != nil &amp;&amp; line != "" </span><span class="cov8" title="1">{
lines = append(lines, line.(string))
}</span>
}
<span class="cov8" title="1">w.Write([]byte( strings.Join(lines, ",") ))</span>
}
func (this *Server) GetMd5File(w http.ResponseWriter, r *http.Request) <span class="cov0" title="0">{
var (
date string
fpath string
data []byte
err error
)
if !this.IsPeer(r) </span><span class="cov0" title="0">{
return
}</span>
<span class="cov0" title="0">fpath = DATA_DIR + "/" + date + "/" + CONST_FILE_Md5_FILE_NAME
if !this.util.FileExists(fpath) </span><span class="cov0" title="0">{
w.WriteHeader(404)
return
}</span>
<span class="cov0" title="0">if data, err = ioutil.ReadFile(fpath); err != nil </span><span class="cov0" title="0">{
w.WriteHeader(500)
return
}</span>
<span class="cov0" title="0">w.Write(data)</span>
}
func (this *Server) GetMd5sMapByDate(date string, filename string) (*CommonMap, error) <span class="cov0" title="0">{
var (
err error
result *CommonMap
fpath string
content string
lines []string
line string
cols []string
data []byte
)
result = &amp;CommonMap{m: make(map[string]interface{})}
if filename == "" </span><span class="cov0" title="0">{
fpath = DATA_DIR + "/" + date + "/" + CONST_FILE_Md5_FILE_NAME
}</span><span class="cov0" title="0"> else {
fpath = DATA_DIR + "/" + date + "/" + filename
}</span>
<span class="cov0" title="0">if !this.util.FileExists(fpath) </span><span class="cov0" title="0">{
return result, errors.New(fmt.Sprintf("fpath %s not found", fpath))
}</span>
<span class="cov0" title="0">if data, err = ioutil.ReadFile(fpath); err != nil </span><span class="cov0" title="0">{
return result, err
}</span>
<span class="cov0" title="0">content = string(data)
lines = strings.Split(content, "\n")
for _, line = range lines </span><span class="cov0" title="0">{
cols = strings.Split(line, "|")
if len(cols) &gt; 2 </span><span class="cov0" title="0">{
if _, err = strconv.ParseInt(cols[1], 10, 64); err != nil </span><span class="cov0" title="0">{
continue</span>
}
<span class="cov0" title="0">result.Add(cols[0])</span>
}
}
<span class="cov0" title="0">return result, nil</span>
}
func (this *Server) GetMd5sByDate(date string, filename string) (mapset.Set, error) <span class="cov8" title="1">{
var (
err error
result mapset.Set
fpath string
content string
lines []string
line string
cols []string
data []byte
sumkey string
ok bool
mds []interface{}
v interface{}
)
sumkey = fmt.Sprintf("%s_%s", date, filename)
if v, ok = this.sumMap.GetValue(sumkey); ok </span><span class="cov8" title="1">{
result = v.(mapset.Set)
if result.Cardinality() &gt; 0 </span><span class="cov8" title="1">{
return result, nil
}</span>
}
<span class="cov8" title="1">result = mapset.NewSet()
if filename == "" </span><span class="cov0" title="0">{
fpath = DATA_DIR + "/" + date + "/" + CONST_FILE_Md5_FILE_NAME
}</span><span class="cov8" title="1"> else {
fpath = DATA_DIR + "/" + date + "/" + filename
}</span>
<span class="cov8" title="1">if !this.util.FileExists(fpath) </span><span class="cov0" title="0">{
os.MkdirAll(DATA_DIR+"/"+date, 0775)
log.Warn(fmt.Sprintf("fpath %s not found", fpath))
return result, nil
}</span>
<span class="cov8" title="1">if data, err = ioutil.ReadFile(fpath); err != nil </span><span class="cov0" title="0">{
return result, err
}</span>
<span class="cov8" title="1">content = string(data)
lines = strings.Split(content, "\n")
if len(lines) &gt; 0 </span><span class="cov8" title="1">{
mds = make([]interface{}, len(lines)-1)
}</span><span class="cov0" title="0"> else {
return result, nil
}</span>
<span class="cov8" title="1">for _, line = range lines </span><span class="cov8" title="1">{
cols = strings.Split(line, "|")
if len(cols) &gt; 2 </span><span class="cov8" title="1">{
if _, err = strconv.ParseInt(cols[1], 10, 64); err != nil </span><span class="cov0" title="0">{
continue</span>
}
<span class="cov8" title="1">mds = append(mds, cols[0])</span>
}
}
<span class="cov8" title="1">result = mapset.NewSetFromSlice(mds)
this.sumMap.Put(sumkey, result)
return result, nil</span>
}
func (this *Server) SyncFileInfo(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
err error
fileInfo FileInfo
fileInfoStr string
filename string
)
r.ParseForm()
if !this.IsPeer(r) </span><span class="cov0" title="0">{
return
}</span>
<span class="cov8" title="1">fileInfoStr = r.FormValue("fileInfo")
if err = json.Unmarshal([]byte(fileInfoStr), &amp;fileInfo); err != nil </span><span class="cov0" title="0">{
w.Write([]byte(this.GetClusterNotPermitMessage(r)))
log.Error(err)
return
}</span>
<span class="cov8" title="1">this.SaveFileMd5Log(&amp;fileInfo, CONST_Md5_QUEUE_FILE_NAME)
go this.AppendToDownloadQueue(&amp;fileInfo)
filename = fileInfo.Name
if fileInfo.ReName != "" </span><span class="cov8" title="1">{
filename = fileInfo.ReName
}</span>
<span class="cov8" title="1">p := strings.Replace(fileInfo.Path, STORE_DIR+"/", "", 1)
downloadUrl := fmt.Sprintf("http://%s/%s", r.Host, Config().Group+"/"+p+"/"+filename)
w.Write([]byte(downloadUrl))</span>
}
func (this *Server) CheckScene(scene string) (bool, error) <span class="cov8" title="1">{
if len(Config().Scenes) == 0 </span><span class="cov8" title="1">{
return true, nil
}</span>
<span class="cov0" title="0">if !this.util.Contains(scene, Config().Scenes) </span><span class="cov0" title="0">{
return false, errors.New("not valid scene")
}</span>
<span class="cov0" title="0">return true, nil</span>
}
func (this *Server) RemoveFile(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
err error
md5sum string
md5path string
fileInfo *FileInfo
fpath string
delUrl string
result JsonResult
inner string
name string
)
_ = delUrl
_ = inner
r.ParseForm()
md5sum = r.FormValue("md5")
fpath = r.FormValue("path")
inner = r.FormValue("inner")
result.Status = "fail"
if fpath != "" &amp;&amp; md5sum == "" </span><span class="cov0" title="0">{
md5sum = this.util.MD5(fpath)
}</span>
<span class="cov8" title="1">if len(md5sum) &lt; 32 </span><span class="cov0" title="0">{
result.Message = "md5 unvalid"
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
<span class="cov8" title="1">if fileInfo, err = this.GetFileInfoFromLevelDB(md5sum); err != nil </span><span class="cov0" title="0">{
w.Write([]byte(err.Error()))
return
}</span>
<span class="cov8" title="1">name = fileInfo.Name
if fileInfo.ReName != "" </span><span class="cov8" title="1">{
name = fileInfo.ReName
}</span>
<span class="cov8" title="1">md5path = this.util.MD5(fileInfo.Path + "/" + name)
if fileInfo.ReName != "" </span><span class="cov8" title="1">{
fpath = fileInfo.Path + "/" + fileInfo.ReName
}</span><span class="cov0" title="0"> else {
fpath = fileInfo.Path + "/" + fileInfo.Name
}</span>
<span class="cov8" title="1">if fileInfo.Path != "" &amp;&amp; this.util.FileExists(fpath) </span><span class="cov0" title="0">{
this.ldb.Delete([]byte(fileInfo.Md5), nil)
this.ldb.Delete([]byte(md5path), nil)
if err = os.Remove(fpath); err != nil </span><span class="cov0" title="0">{
w.Write([]byte(err.Error()))
return
}</span><span class="cov0" title="0"> else {
//if inner!="1" {
// for _, peer := range Config().Peers {
// delUrl = fmt.Sprintf("%s%s", peer, this.getRequestURI("delete"))
// req := httplib.Post(delUrl)
// req.Param("md5", fileInfo.Md5)
// req.Param("inner", "1")
// req.SetTimeout(time.Second*5, time.Second*10)
// if _, err = req.String(); err != nil {
// log.Error(err)
// }
// }
//}
this.SaveFileMd5Log(fileInfo, CONST_REMOME_Md5_FILE_NAME)
result.Message = "remove success"
result.Status = "ok"
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
}
<span class="cov8" title="1">result.Message = "fail remove"
w.Write([]byte(this.util.JsonEncodePretty(result)))</span>
}
func (this *Server) getRequestURI(action string) string <span class="cov8" title="1">{
var (
uri string
)
if Config().SupportGroupManage </span><span class="cov0" title="0">{
uri = "/" + Config().Group + "/" + action
}</span><span class="cov8" title="1"> else {
uri = "/" + action
}</span>
<span class="cov8" title="1">return uri</span>
}
func (this *Server) BuildFileResult(fileInfo *FileInfo, r *http.Request) FileResult <span class="cov8" title="1">{
var (
outname string
fileResult FileResult
p string
downloadUrl string
domain string
)
if Config().DownloadDomain != "" </span><span class="cov0" title="0">{
domain = fmt.Sprintf("http://%s", Config().DownloadDomain)
}</span><span class="cov8" title="1"> else {
domain = fmt.Sprintf("http://%s", r.Host)
}</span>
<span class="cov8" title="1">outname = fileInfo.Name
if fileInfo.ReName != "" </span><span class="cov8" title="1">{
outname = fileInfo.ReName
}</span>
<span class="cov8" title="1">p = strings.Replace(fileInfo.Path, STORE_DIR_NAME+"/", "", 1)
p = Config().Group + "/" + p + "/" + outname
downloadUrl = fmt.Sprintf("http://%s/%s", r.Host, p)
if Config().DownloadDomain != "" </span><span class="cov0" title="0">{
downloadUrl = fmt.Sprintf("http://%s/%s", Config().DownloadDomain, p)
}</span>
<span class="cov8" title="1">fileResult.Url = downloadUrl
fileResult.Md5 = fileInfo.Md5
fileResult.Path = "/" + p
fileResult.Domain = domain
fileResult.Scene = fileInfo.Scene
// Just for Compatibility
fileResult.Src = fileResult.Path
fileResult.Scenes = fileInfo.Scene
return fileResult</span>
}
func (this *Server) SaveUploadFile(file multipart.File, header *multipart.FileHeader, fileInfo *FileInfo, r *http.Request) (*FileInfo, error) <span class="cov8" title="1">{
var (
err error
outFile *os.File
folder string
fi os.FileInfo
)
defer file.Close()
fileInfo.Name = header.Filename
if Config().RenameFile </span><span class="cov0" title="0">{
fileInfo.ReName = this.util.MD5(this.util.GetUUID()) + path.Ext(fileInfo.Name)
}</span>
<span class="cov8" title="1">folder = time.Now().Format("20060102/15/04")
if Config().PeerId != "" </span><span class="cov8" title="1">{
folder = fmt.Sprintf(folder+"/%s", Config().PeerId)
}</span>
<span class="cov8" title="1">if fileInfo.Scene != "" </span><span class="cov8" title="1">{
folder = fmt.Sprintf(STORE_DIR+"/%s/%s", fileInfo.Scene, folder)
}</span><span class="cov0" title="0"> else {
folder = fmt.Sprintf(STORE_DIR+"/%s", folder)
}</span>
<span class="cov8" title="1">if fileInfo.Path != "" </span><span class="cov0" title="0">{
if strings.HasPrefix(fileInfo.Path, STORE_DIR) </span><span class="cov0" title="0">{
folder = fileInfo.Path
}</span><span class="cov0" title="0"> else {
folder = STORE_DIR + "/" + fileInfo.Path
}</span>
}
<span class="cov8" title="1">if !this.util.FileExists(folder) </span><span class="cov0" title="0">{
os.MkdirAll(folder, 0775)
}</span>
<span class="cov8" title="1">outPath := fmt.Sprintf(folder+"/%s", fileInfo.Name)
if Config().RenameFile </span><span class="cov0" title="0">{
outPath = fmt.Sprintf(folder+"/%s", fileInfo.ReName)
}</span>
<span class="cov8" title="1">if this.util.FileExists(outPath) </span><span class="cov0" title="0">{
for i := 0; i &lt; 10000; i++ </span><span class="cov0" title="0">{
outPath = fmt.Sprintf(folder+"/%d_%s", i, header.Filename)
fileInfo.Name = fmt.Sprintf("%d_%s", i, header.Filename)
if !this.util.FileExists(outPath) </span><span class="cov0" title="0">{
break</span>
}
}
}
<span class="cov8" title="1">log.Info(fmt.Sprintf("upload: %s", outPath))
if outFile, err = os.Create(outPath); err != nil </span><span class="cov0" title="0">{
return fileInfo, err
}</span>
<span class="cov8" title="1">defer outFile.Close()
if err != nil </span><span class="cov0" title="0">{
log.Error(err)
return fileInfo, errors.New("(error)fail," + err.Error())
}</span>
<span class="cov8" title="1">if _, err = io.Copy(outFile, file); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return fileInfo, errors.New("(error)fail," + err.Error())
}</span>
<span class="cov8" title="1">if fi, err = outFile.Stat(); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span><span class="cov8" title="1"> else {
fileInfo.Size = fi.Size()
}</span>
<span class="cov8" title="1">if fi.Size() != header.Size </span><span class="cov0" title="0">{
return fileInfo, errors.New("(error)file uncomplete")
}</span>
<span class="cov8" title="1">v := this.util.GetFileSum(outFile, Config().FileSumArithmetic)
fileInfo.Md5 = v
//fileInfo.Path = folder //strings.Replace( folder,DOCKER_DIR,"",1)
fileInfo.Path = strings.Replace(folder, DOCKER_DIR, "", 1)
fileInfo.Peers = append(fileInfo.Peers, fmt.Sprintf("http://%s", r.Host))
//fmt.Println("upload",fileInfo)
return fileInfo, nil</span>
}
func (this *Server) Upload(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
err error
// pathname string
md5sum string
fileInfo FileInfo
uploadFile multipart.File
uploadHeader *multipart.FileHeader
scene string
output string
fileResult FileResult
data []byte
)
//r.ParseForm()
if r.Method == "POST" </span><span class="cov8" title="1">{
// name := r.PostFormValue("name")
// fileInfo.Path = r.Header.Get("Sync-Path")
md5sum = r.FormValue("md5")
output = r.FormValue("output")
//if strings.Contains(r.Host, "127.0.0.1") {
// w.Write([]byte( "(error) upload use clust ip(peers ip),not 127.0.0.1"))
// return
//}
if Config().EnableCustomPath </span><span class="cov8" title="1">{
fileInfo.Path = r.FormValue("path")
fileInfo.Path = strings.Trim(fileInfo.Path, "/")
}</span>
<span class="cov8" title="1">scene = r.FormValue("scene")
if scene == "" </span><span class="cov8" title="1">{
//Just for Compatibility
scene = r.FormValue("scenes")
}</span>
<span class="cov8" title="1">fileInfo.Md5 = md5sum
fileInfo.OffSet = -1
if uploadFile, uploadHeader, err = r.FormFile("file"); err != nil </span><span class="cov0" title="0">{
log.Error(err)
w.Write([]byte(err.Error()))
return
}</span>
<span class="cov8" title="1">fileInfo.Peers = []string{}
fileInfo.TimeStamp = time.Now().Unix()
if scene == "" </span><span class="cov8" title="1">{
scene = Config().DefaultScene
}</span>
<span class="cov8" title="1">if output == "" </span><span class="cov0" title="0">{
output = "text"
}</span>
<span class="cov8" title="1">if !this.util.Contains(output, []string{"json", "text"}) </span><span class="cov0" title="0">{
w.Write([]byte("output just support json or text"))
return
}</span>
<span class="cov8" title="1">fileInfo.Scene = scene
if _, err = this.CheckScene(scene); err != nil </span><span class="cov0" title="0">{
w.Write([]byte(err.Error()))
return
}</span>
<span class="cov8" title="1">if err != nil </span><span class="cov0" title="0">{
log.Error(err)
http.Redirect(w, r, "/", http.StatusMovedPermanently)
return
}</span>
<span class="cov8" title="1">if _, err = this.SaveUploadFile(uploadFile, uploadHeader, &amp;fileInfo, r); err != nil </span><span class="cov0" title="0">{
w.Write([]byte(err.Error()))
return
}</span>
<span class="cov8" title="1">if v, _ := this.GetFileInfoFromLevelDB(fileInfo.Md5); v != nil &amp;&amp; v.Md5 != "" </span><span class="cov0" title="0">{
fileResult = this.BuildFileResult(v, r)
if Config().RenameFile </span><span class="cov0" title="0">{
os.Remove(DOCKER_DIR + fileInfo.Path + "/" + fileInfo.ReName)
}</span><span class="cov0" title="0"> else {
os.Remove(DOCKER_DIR + fileInfo.Path + "/" + fileInfo.Name)
}</span>
<span class="cov0" title="0">if output == "json" </span><span class="cov0" title="0">{
if data, err = json.Marshal(fileResult); err != nil </span><span class="cov0" title="0">{
log.Error(err)
w.Write([]byte(err.Error()))
}</span>
<span class="cov0" title="0">w.Write(data)</span>
}<span class="cov0" title="0"> else {
w.Write([]byte(fileResult.Url))
}</span>
<span class="cov0" title="0">return</span>
}
<span class="cov8" title="1">if fileInfo.Md5 == "" </span><span class="cov0" title="0">{
log.Warn(" fileInfo.Md5 is null")
return
}</span>
<span class="cov8" title="1">if md5sum != "" &amp;&amp; fileInfo.Md5 != md5sum </span><span class="cov0" title="0">{
log.Warn(" fileInfo.Md5 and md5sum !=")
return
}</span>
<span class="cov8" title="1">if Config().EnableMergeSmallFile &amp;&amp; fileInfo.Size &lt; CONST_SMALL_FILE_SIZE </span><span class="cov8" title="1">{
if err = this.SaveSmallFile(&amp;fileInfo); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return
}</span>
}
<span class="cov8" title="1">go this.postFileToPeer(&amp;fileInfo)
if fileInfo.Size &lt;= 0 </span><span class="cov0" title="0">{
log.Error("file size is zero")
return
}</span>
<span class="cov8" title="1">fileResult = this.BuildFileResult(&amp;fileInfo, r)
this.SaveFileMd5Log(&amp;fileInfo, CONST_FILE_Md5_FILE_NAME)
if output == "json" </span><span class="cov8" title="1">{
if data, err = json.Marshal(fileResult); err != nil </span><span class="cov0" title="0">{
log.Error(err)
w.Write([]byte(err.Error()))
}</span>
<span class="cov8" title="1">w.Write(data)</span>
}<span class="cov0" title="0"> else {
w.Write([]byte(fileResult.Url))
}</span>
<span class="cov8" title="1">return</span>
}<span class="cov0" title="0"> else {
md5sum = r.FormValue("md5")
output = r.FormValue("output")
if md5sum == "" </span><span class="cov0" title="0">{
w.Write([]byte("(error) if you want to upload fast md5 is require" +
",and if you want to upload file,you must use post method "))
return
}</span>
<span class="cov0" title="0">if v, _ := this.GetFileInfoFromLevelDB(md5sum); v != nil &amp;&amp; v.Md5 != "" </span><span class="cov0" title="0">{
fileResult = this.BuildFileResult(v, r)
if output == "json" </span><span class="cov0" title="0">{
if data, err = json.Marshal(fileResult); err != nil </span><span class="cov0" title="0">{
log.Error(err)
w.Write([]byte(err.Error()))
}</span>
<span class="cov0" title="0">w.Write(data)</span>
}<span class="cov0" title="0"> else {
w.Write([]byte(fileResult.Url))
}</span>
<span class="cov0" title="0">return</span>
}
<span class="cov0" title="0">w.Write([]byte("(error)fail,please use post method"))
return</span>
}
}
func (this *Server) SaveSmallFile(fileInfo *FileInfo) (error) <span class="cov8" title="1">{
var (
err error
filename string
fpath string
srcFile *os.File
desFile *os.File
largeDir string
destPath string
reName string
)
filename = fileInfo.Name
if fileInfo.ReName != "" </span><span class="cov0" title="0">{
filename = fileInfo.ReName
}</span>
<span class="cov8" title="1">fpath = DOCKER_DIR + fileInfo.Path + "/" + filename
largeDir = LARGE_DIR + "/" + Config().PeerId
if !this.util.FileExists(largeDir) </span><span class="cov0" title="0">{
os.MkdirAll(largeDir, 0775)
}</span>
<span class="cov8" title="1">reName = fmt.Sprintf("%d", this.util.RandInt(100, 300))
destPath = largeDir + "/" + reName
this.lockMap.LockKey(destPath)
defer this.lockMap.UnLockKey(destPath)
if this.util.FileExists(fpath) </span><span class="cov8" title="1">{
srcFile, err = os.OpenFile(fpath, os.O_CREATE|os.O_RDONLY, 06666)
if err != nil </span><span class="cov0" title="0">{
return err
}</span>
<span class="cov8" title="1">defer srcFile.Close()
desFile, err = os.OpenFile(destPath, os.O_CREATE|os.O_RDWR, 06666)
if err != nil </span><span class="cov0" title="0">{
return err
}</span>
<span class="cov8" title="1">defer desFile.Close()
fileInfo.OffSet, err = desFile.Seek(0, 2)
if _, err = desFile.Write([]byte("1")); err != nil </span><span class="cov0" title="0">{ //first byte set 1
return err
}</span>
<span class="cov8" title="1">fileInfo.OffSet, err = desFile.Seek(0, 2)
if err != nil </span><span class="cov0" title="0">{
return err
}</span>
<span class="cov8" title="1">fileInfo.OffSet = fileInfo.OffSet - 1 //minus 1 byte
fileInfo.Size = fileInfo.Size + 1
fileInfo.ReName = fmt.Sprintf("%s,%d,%d", reName, fileInfo.OffSet, fileInfo.Size)
if _, err = io.Copy(desFile, srcFile); err != nil </span><span class="cov0" title="0">{
return err
}</span>
<span class="cov8" title="1">srcFile.Close()
os.Remove(fpath)
fileInfo.Path = strings.Replace(largeDir, DOCKER_DIR, "", 1)</span>
}
<span class="cov8" title="1">return nil</span>
}
func (this *Server) SendToMail(to, subject, body, mailtype string) error <span class="cov0" title="0">{
host := Config().Mail.Host
user := Config().Mail.User
password := Config().Mail.Password
hp := strings.Split(host, ":")
auth := smtp.PlainAuth("", user, password, hp[0])
var contentType string
if mailtype == "html" </span><span class="cov0" title="0">{
contentType = "Content-Type: text/" + mailtype + "; charset=UTF-8"
}</span><span class="cov0" title="0"> else {
contentType = "Content-Type: text/plain" + "; charset=UTF-8"
}</span>
<span class="cov0" title="0">msg := []byte("To: " + to + "\r\nFrom: " + user + "&gt;\r\nSubject: " + "\r\n" + contentType + "\r\n\r\n" + body)
sendTo := strings.Split(to, ";")
err := smtp.SendMail(host, auth, user, sendTo, msg)
return err</span>
}
func (this *Server) BenchMark(w http.ResponseWriter, r *http.Request) <span class="cov0" title="0">{
t := time.Now()
batch := new(leveldb.Batch)
for i := 0; i &lt; 100000000; i++ </span><span class="cov0" title="0">{
f := FileInfo{}
f.Peers = []string{"http://192.168.0.1", "http://192.168.2.5"}
f.Path = "20190201/19/02"
s := strconv.Itoa(i)
s = this.util.MD5(s)
f.Name = s
f.Md5 = s
// server.SaveFileInfoToLevelDB(s, &amp;f)
if data, err := json.Marshal(&amp;f); err == nil </span><span class="cov0" title="0">{
batch.Put([]byte(s), data)
}</span>
<span class="cov0" title="0">if i%10000 == 0 </span><span class="cov0" title="0">{
if batch.Len() &gt; 0 </span><span class="cov0" title="0">{
server.ldb.Write(batch, nil)
// batch = new(leveldb.Batch)
batch.Reset()
}</span>
<span class="cov0" title="0">fmt.Println(i, time.Since(t).Seconds())</span>
}
//fmt.Println(server.GetFileInfoFromLevelDB(s))
}
<span class="cov0" title="0">this.util.WriteFile("time.txt", time.Since(t).String())
fmt.Println(time.Since(t).String())</span>
}
func (this *Server) RepairStatWeb(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
result JsonResult
)
this.RepairStat()
result.Status = "ok"
w.Write([]byte(this.util.JsonEncodePretty(result)))
}</span>
func (this *Server) Stat(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
result JsonResult
inner string
)
r.ParseForm()
inner = r.FormValue("inner")
data := this.GetStat()
result.Status = "ok"
result.Data = data
if inner == "1" </span><span class="cov8" title="1">{
w.Write([]byte(this.util.JsonEncodePretty(data)))
}</span><span class="cov8" title="1"> else {
w.Write([]byte(this.util.JsonEncodePretty(result)))
}</span>
}
func (this *Server) GetStat() []StatDateFileInfo <span class="cov8" title="1">{
var (
min int64
max int64
err error
i int64
rows []StatDateFileInfo
)
min = 20190101
max = 20190101
for k := range this.statMap.Get() </span><span class="cov8" title="1">{
ks := strings.Split(k, "_")
if len(ks) == 2 </span><span class="cov8" title="1">{
if i, err = strconv.ParseInt(ks[0], 10, 64); err != nil </span><span class="cov0" title="0">{
continue</span>
}
<span class="cov8" title="1">if i &gt;= max </span><span class="cov8" title="1">{
max = i
}</span>
<span class="cov8" title="1">if i &lt; min </span><span class="cov0" title="0">{
min = i
}</span>
}
}
<span class="cov8" title="1">for i := min; i &lt;= max; i++ </span><span class="cov8" title="1">{
s := fmt.Sprintf("%d", i)
if v, ok := this.statMap.GetValue(s + "_" + CONST_STAT_FILE_TOTAL_SIZE_KEY); ok </span><span class="cov8" title="1">{
var info StatDateFileInfo
info.Date = s
switch v.(type) </span>{
case int64:<span class="cov8" title="1">
info.TotalSize = v.(int64)</span>
}
<span class="cov8" title="1">if v, ok := this.statMap.GetValue(s + "_" + CONST_STAT_FILE_COUNT_KEY); ok </span><span class="cov8" title="1">{
switch v.(type) </span>{
case int64:<span class="cov8" title="1">
info.FileCount = v.(int64)</span>
}
}
<span class="cov8" title="1">rows = append(rows, info)</span>
}
}
<span class="cov8" title="1">if v, ok := this.statMap.GetValue(CONST_STAT_FILE_COUNT_KEY); ok </span><span class="cov8" title="1">{
var info StatDateFileInfo
info.Date = "all"
info.FileCount = v.(int64)
if v, ok := this.statMap.GetValue(CONST_STAT_FILE_TOTAL_SIZE_KEY); ok </span><span class="cov8" title="1">{
info.TotalSize = v.(int64)
}</span>
<span class="cov8" title="1">rows = append(rows, info)</span>
}
<span class="cov8" title="1">return rows</span>
}
func (this *Server) RegisterExit() <span class="cov0" title="0">{
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() </span><span class="cov0" title="0">{
for s := range c </span><span class="cov0" title="0">{
switch s </span>{
case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT:<span class="cov0" title="0">
this.ldb.Close()
log.Info("Exit", s)
os.Exit(1)</span>
}
}
}()
}
func (this *Server) AppendToQueue(fileInfo *FileInfo) <span class="cov8" title="1">{
this.queueToPeers &lt;- *fileInfo
}</span>
func (this *Server) AppendToDownloadQueue(fileInfo *FileInfo) <span class="cov8" title="1">{
this.queueFromPeers &lt;- *fileInfo
}</span>
func (this *Server) ConsumerDownLoad() <span class="cov8" title="1">{
ConsumerFunc := func() </span><span class="cov8" title="1">{
for </span><span class="cov8" title="1">{
fileInfo := &lt;-this.queueFromPeers
if len(fileInfo.Peers) &lt;= 0 </span><span class="cov0" title="0">{
log.Warn("Peer is null", fileInfo)
continue</span>
}
<span class="cov8" title="1">for _, peer := range fileInfo.Peers </span><span class="cov8" title="1">{
if strings.Contains(peer, "127.0.0.1") </span><span class="cov0" title="0">{
log.Warn("sync error with 127.0.0.1", fileInfo)
continue</span>
}
<span class="cov8" title="1">if peer != this.host </span><span class="cov8" title="1">{
this.DownloadFromPeer(peer, &amp;fileInfo)
break</span>
}
}
}
}
<span class="cov8" title="1">for i := 0; i &lt; 50; i++ </span><span class="cov8" title="1">{
go ConsumerFunc()
}</span>
}
func (this *Server) Consumer() <span class="cov8" title="1">{
ConsumerFunc := func() </span><span class="cov8" title="1">{
for </span><span class="cov8" title="1">{
fileInfo := &lt;-this.queueToPeers
this.postFileToPeer(&amp;fileInfo)
}</span>
}
<span class="cov8" title="1">for i := 0; i &lt; 50; i++ </span><span class="cov8" title="1">{
go ConsumerFunc()
}</span>
}
func (this *Server) AutoRepair(forceRepair bool) <span class="cov8" title="1">{
if this.lockMap.IsLock("AutoRepair") </span><span class="cov0" title="0">{
log.Warn("Lock AutoRepair")
return
}</span>
<span class="cov8" title="1">this.lockMap.LockKey("AutoRepair")
defer this.lockMap.UnLockKey("AutoRepair")
AutoRepairFunc := func(forceRepair bool) </span><span class="cov8" title="1">{
var (
dateStats []StatDateFileInfo
err error
countKey string
md5s string
localSet mapset.Set
remoteSet mapset.Set
allSet mapset.Set
tmpSet mapset.Set
fileInfo *FileInfo
)
defer func() </span><span class="cov8" title="1">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("AutoRepair")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
<span class="cov8" title="1">Update := func(peer string, dateStat StatDateFileInfo) </span><span class="cov8" title="1">{ //从远端拉数据过来
req := httplib.Get(fmt.Sprintf("%s%s?date=%s&amp;force=%s", peer, this.getRequestURI("sync"), dateStat.Date, "1"))
req.SetTimeout(time.Second*5, time.Second*5)
if _, err = req.String(); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
<span class="cov8" title="1">log.Info(fmt.Sprintf("syn file from %s date %s", peer, dateStat.Date))</span>
}
<span class="cov8" title="1">for _, peer := range Config().Peers </span><span class="cov8" title="1">{
req := httplib.Post(fmt.Sprintf("%s%s", peer, this.getRequestURI("stat")))
req.Param("inner", "1")
req.SetTimeout(time.Second*5, time.Second*15)
if err = req.ToJSON(&amp;dateStats); err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov8" title="1">for _, dateStat := range dateStats </span><span class="cov8" title="1">{
if dateStat.Date == "all" </span><span class="cov8" title="1">{
continue</span>
}
<span class="cov8" title="1">countKey = dateStat.Date + "_" + CONST_STAT_FILE_COUNT_KEY
if v, ok := this.statMap.GetValue(countKey); ok </span><span class="cov8" title="1">{
switch v.(type) </span>{
case int64:<span class="cov8" title="1">
if v.(int64) != dateStat.FileCount || forceRepair </span><span class="cov8" title="1">{ //不相等,找差异
//TODO
req := httplib.Post(fmt.Sprintf("%s%s", peer, this.getRequestURI("get_md5s_by_date")))
req.SetTimeout(time.Second*15, time.Second*60)
req.Param("date", dateStat.Date)
if md5s, err = req.String(); err != nil </span><span class="cov0" title="0">{
continue</span>
}
<span class="cov8" title="1">if localSet, err = this.GetMd5sByDate(dateStat.Date, CONST_FILE_Md5_FILE_NAME); err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov8" title="1">remoteSet = this.util.StrToMapSet(md5s, ",")
allSet = localSet.Union(remoteSet)
md5s = this.util.MapSetToStr(allSet.Difference(localSet), ",")
req = httplib.Post(fmt.Sprintf("%s%s", peer, this.getRequestURI("receive_md5s")))
req.SetTimeout(time.Second*15, time.Second*60)
req.Param("md5s", md5s)
req.String()
tmpSet = allSet.Difference(remoteSet)
for v := range tmpSet.Iter() </span><span class="cov8" title="1">{
if v != nil </span><span class="cov8" title="1">{
if fileInfo, err = this.GetFileInfoFromLevelDB(v.(string)); err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov8" title="1">this.AppendToQueue(fileInfo)</span>
}
}
//Update(peer,dateStat)
}
}
}<span class="cov8" title="1"> else {
Update(peer, dateStat)
}</span>
}
}
}
<span class="cov8" title="1">AutoRepairFunc(forceRepair)</span>
}
func (this *Server) CleanMd5SumCache() <span class="cov8" title="1">{
Clean := func() </span><span class="cov8" title="1">{
defer func() </span><span class="cov8" title="1">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("Check")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
<span class="cov8" title="1">var (
today string
memstat *runtime.MemStats
keys []string
)
memstat = new(runtime.MemStats)
runtime.ReadMemStats(memstat)
_ = memstat
today = this.util.GetToDay()
_ = today
keys = this.sumMap.Keys()
for _, k := range keys </span><span class="cov0" title="0">{
if strings.HasPrefix(k, today) </span><span class="cov0" title="0">{
continue</span>
}
<span class="cov0" title="0">if v, ok := this.sumMap.GetValue(k); ok </span><span class="cov0" title="0">{
v.(mapset.Set).Clear()
}</span>
}
}
<span class="cov8" title="1">go func() </span><span class="cov8" title="1">{
for </span><span class="cov8" title="1">{
Clean()
time.Sleep(time.Minute * 10)
}</span>
}()
}
func (this *Server) Check() <span class="cov8" title="1">{
check := func() </span><span class="cov8" title="1">{
defer func() </span><span class="cov8" title="1">{
if re := recover(); re != nil </span><span class="cov0" title="0">{
buffer := debug.Stack()
log.Error("Check")
log.Error(re)
log.Error(string(buffer))
}</span>
}()
<span class="cov8" title="1">var (
status JsonResult
err error
subject string
body string
req *httplib.BeegoHTTPRequest
)
for _, peer := range Config().Peers </span><span class="cov8" title="1">{
req = httplib.Get(fmt.Sprintf("%s%s", peer, this.getRequestURI("status")))
req.SetTimeout(time.Second*5, time.Second*5)
err = req.ToJSON(&amp;status)
if status.Status != "ok" </span><span class="cov0" title="0">{
for _, to := range Config().AlramReceivers </span><span class="cov0" title="0">{
subject = "fastdfs server error"
if err != nil </span><span class="cov0" title="0">{
body = fmt.Sprintf("%s\nserver:%s\nerror:\n%s", subject, peer, err.Error())
}</span><span class="cov0" title="0"> else {
body = fmt.Sprintf("%s\nserver:%s\n", subject, peer)
}</span>
<span class="cov0" title="0">if err = this.SendToMail(to, subject, body, "text"); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
}
<span class="cov0" title="0">if Config().AlarmUrl != "" </span><span class="cov0" title="0">{
req = httplib.Post(Config().AlarmUrl)
req.SetTimeout(time.Second*10, time.Second*10)
req.Param("message", body)
req.Param("subject", subject)
if _, err = req.String(); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
}
}
}
}
<span class="cov8" title="1">go func() </span><span class="cov8" title="1">{
for </span><span class="cov8" title="1">{
check()
time.Sleep(time.Minute * 10)
}</span>
}()
}
func (this *Server) RepairFileInfo(w http.ResponseWriter, r *http.Request) <span class="cov0" title="0">{
var (
result JsonResult
)
if !this.IsPeer(r) </span><span class="cov0" title="0">{
w.Write([]byte(this.GetClusterNotPermitMessage(r)))
return
}</span>
<span class="cov0" title="0">result.Status = "ok"
result.Message = "repair job start,don't try again"
go this.RepairFileInfoFromFile()
w.Write([]byte(this.util.JsonEncodePretty(result)))</span>
}
func (this *Server) Reload(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
err error
data []byte
cfg GloablConfig
action string
cfgjson string
result JsonResult
)
result.Status = "fail"
r.ParseForm()
if !this.IsPeer(r) </span><span class="cov0" title="0">{
w.Write([]byte(this.GetClusterNotPermitMessage(r)))
return
}</span>
<span class="cov8" title="1">cfgjson = r.FormValue("cfg")
action = r.FormValue("action")
_ = cfgjson
if action == "get" </span><span class="cov8" title="1">{
result.Data = Config()
result.Status = "ok"
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
<span class="cov8" title="1">if action == "set" </span><span class="cov8" title="1">{
if cfgjson == "" </span><span class="cov0" title="0">{
result.Message = "(error)parameter cfg(json) require"
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
<span class="cov8" title="1">if err = json.Unmarshal([]byte(cfgjson), &amp;cfg); err != nil </span><span class="cov0" title="0">{
log.Error(err)
result.Message = err.Error()
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
<span class="cov8" title="1">result.Status = "ok"
cfgjson = this.util.JsonEncodePretty(cfg)
this.util.WriteFile(CONST_CONF_FILE_NAME, cfgjson)
w.Write([]byte(this.util.JsonEncodePretty(result)))
return</span>
}
<span class="cov8" title="1">if action == "reload" </span><span class="cov8" title="1">{
if data, err = ioutil.ReadFile(CONST_CONF_FILE_NAME); err != nil </span><span class="cov0" title="0">{
result.Message = err.Error()
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
<span class="cov8" title="1">if err = json.Unmarshal(data, &amp;cfg); err != nil </span><span class="cov0" title="0">{
result.Message = err.Error()
w.Write([]byte(this.util.JsonEncodePretty(result)))
return
}</span>
<span class="cov8" title="1">ParseConfig(CONST_CONF_FILE_NAME)
this.initComponent(true)
result.Status = "ok"
w.Write([]byte(this.util.JsonEncodePretty(result)))
return</span>
}
<span class="cov0" title="0">if action == "" </span><span class="cov0" title="0">{
w.Write([]byte("(error)action support set(json) get reload"))
}</span>
}
func (this *Server) Repair(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
force string
forceRepair bool
result JsonResult
)
result.Status = "ok"
r.ParseForm()
force = r.FormValue("force")
if force == "1" </span><span class="cov8" title="1">{
forceRepair = true
}</span>
<span class="cov8" title="1">if this.IsPeer(r) </span><span class="cov8" title="1">{
go this.AutoRepair(forceRepair)
result.Message = "repair job start..."
w.Write([]byte(this.util.JsonEncodePretty(result)))
}</span><span class="cov0" title="0"> else {
result.Message = this.GetClusterNotPermitMessage(r)
w.Write([]byte(this.util.JsonEncodePretty(result)))
}</span>
}
func (this *Server) Status(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
status JsonResult
err error
data []byte
sts map[string]interface{}
today string
sumset mapset.Set
ok bool
v interface{}
)
memStat := new(runtime.MemStats)
runtime.ReadMemStats(memStat)
today = this.util.GetToDay()
sts = make(map[string]interface{})
sts["Fs.QueueFromPeers"] = len(this.queueFromPeers)
sts["Fs.QueueToPeers"] = len(this.queueToPeers)
for _, k := range []string{CONST_FILE_Md5_FILE_NAME, CONST_Md5_ERROR_FILE_NAME, CONST_Md5_QUEUE_FILE_NAME} </span><span class="cov8" title="1">{
k2 := fmt.Sprintf("%s_%s", today, k)
if v, ok = this.sumMap.GetValue(k2); ok </span><span class="cov8" title="1">{
sumset = v.(mapset.Set)
if k == CONST_Md5_QUEUE_FILE_NAME </span><span class="cov0" title="0">{
sts["Fs.QueueSetSize"] = sumset.Cardinality()
}</span>
<span class="cov8" title="1">if k == CONST_Md5_ERROR_FILE_NAME </span><span class="cov8" title="1">{
sts["Fs.ErrorSetSize"] = sumset.Cardinality()
}</span>
<span class="cov8" title="1">if k == CONST_FILE_Md5_FILE_NAME </span><span class="cov8" title="1">{
sts["Fs.FileSetSize"] = sumset.Cardinality()
}</span>
}
}
<span class="cov8" title="1">sts["Fs.AutoRepair"] = Config().AutoRepair
sts["Fs.RefreshInterval"] = Config().RefreshInterval
sts["Fs.Peers"] = Config().Peers
sts["Fs.Local"] = this.host
sts["Fs.FileStats"] = this.GetStat()
sts["Fs.ShowDir"] = Config().ShowDir
sts["Sys.NumGoroutine"] = runtime.NumGoroutine()
sts["Sys.NumCpu"] = runtime.NumCPU()
sts["Sys.Alloc"] = memStat.Alloc
sts["Sys.TotalAlloc"] = memStat.TotalAlloc
sts["Sys.HeapAlloc"] = memStat.HeapAlloc
sts["Sys.Frees"] = memStat.Frees
sts["Sys.HeapObjects"] = memStat.HeapObjects
sts["Sys.NumGC"] = memStat.NumGC
sts["Sys.GCCPUFraction"] = memStat.GCCPUFraction
sts["Sys.GCSys"] = memStat.GCSys
//sts["Sys.MemInfo"] = memStat
status.Status = "ok"
status.Data = sts
w.Write([]byte(this.util.JsonEncodePretty(status)))
return
if data, err = json.Marshal(&amp;status); err != nil </span><span class="cov0" title="0">{
status.Status = "fail"
status.Message = err.Error()
w.Write(data)
return
}</span>
<span class="cov0" title="0">w.Write(data)</span>
}
func (this *Server) HeartBeat(w http.ResponseWriter, r *http.Request) <span class="cov0" title="0">{
}</span>
func (this *Server) Index(w http.ResponseWriter, r *http.Request) <span class="cov8" title="1">{
var (
uploadUrl string
uploadBigUrl string
)
uploadUrl = "/upload"
uploadBigUrl = CONST_BIG_UPLOAD_PATH_SUFFIX
if Config().EnableWebUpload </span><span class="cov8" title="1">{
if Config().SupportGroupManage </span><span class="cov0" title="0">{
uploadUrl = fmt.Sprintf("/%s/upload", Config().Group)
uploadBigUrl = fmt.Sprintf("/%s%s", Config().Group, CONST_BIG_UPLOAD_PATH_SUFFIX)
}</span>
<span class="cov8" title="1">fmt.Fprintf(w,
fmt.Sprintf(`&lt;html&gt;
&lt;head&gt;
&lt;meta charset="utf-8" /&gt;
&lt;title&gt;Uploader&lt;/title&gt;
&lt;style&gt;form { bargin } .form-line { display:block;height: 30px;margin:8px; } #stdUpload {background: #fafafa;border-radius: 10px;width: 745px; }&lt;/style&gt;
&lt;link href="https://transloadit.edgly.net/releases/uppy/v0.30.0/dist/uppy.min.css" rel="stylesheet"&gt;&lt;/head&gt;
&lt;body&gt;
&lt;div&gt;标准上传(强列建议使用这种方式)&lt;/div&gt;
&lt;div id="stdUpload"&gt;
&lt;form action="%s" method="post" enctype="multipart/form-data"&gt;
&lt;span class="form-line"&gt;文件(file):
&lt;input type="file" id="file" name="file" /&gt;&lt;/span&gt;
&lt;span class="form-line"&gt;场景(scene):
&lt;input type="text" id="scene" name="scene" value="%s" /&gt;&lt;/span&gt;
&lt;span class="form-line"&gt;输出(output):
&lt;input type="text" id="output" name="output" value="json" /&gt;&lt;/span&gt;
&lt;span class="form-line"&gt;自定义路径(path):
&lt;input type="text" id="path" name="path" value="" /&gt;&lt;/span&gt;
&lt;input type="submit" name="submit" value="upload" /&gt;&lt;/form&gt;
&lt;/div&gt;
&lt;div&gt;断点续传(如果文件很大时可以考虑)&lt;/div&gt;
&lt;div&gt;
&lt;div id="drag-drop-area"&gt;&lt;/div&gt;
&lt;script src="https://transloadit.edgly.net/releases/uppy/v0.30.0/dist/uppy.min.js"&gt;&lt;/script&gt;
&lt;script&gt;var uppy = Uppy.Core().use(Uppy.Dashboard, {
inline: true,
target: '#drag-drop-area'
}).use(Uppy.Tus, {
endpoint: '%s'
})
uppy.on('complete', (result) =&gt; {
// console.log(result) console.log('Upload complete! Weve uploaded these files:', result.successful)
})
&lt;/script&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;`, uploadUrl, Config().DefaultScene, uploadBigUrl))</span>
}<span class="cov0" title="0"> else {
w.Write([]byte("web upload deny"))
}</span>
}
func init() <span class="cov8" title="1">{
DOCKER_DIR = os.Getenv("GO_FASTDFS_DIR")
if DOCKER_DIR != "" </span><span class="cov0" title="0">{
if !strings.HasSuffix(DOCKER_DIR, "/") </span><span class="cov0" title="0">{
DOCKER_DIR = DOCKER_DIR + "/"
}</span>
}
<span class="cov8" title="1">STORE_DIR = DOCKER_DIR + STORE_DIR_NAME
CONF_DIR = DOCKER_DIR + CONF_DIR_NAME
DATA_DIR = DOCKER_DIR + DATA_DIR_NAME
LOG_DIR = DOCKER_DIR + LOG_DIR_NAME
LARGE_DIR_NAME = "haystack"
LARGE_DIR = STORE_DIR + "/haystack"
CONST_LEVELDB_FILE_NAME = DATA_DIR + "/fileserver.db"
CONST_STAT_FILE_NAME = DATA_DIR + "/stat.json"
CONST_CONF_FILE_NAME = CONF_DIR + "/cfg.json"
FOLDERS = []string{DATA_DIR, STORE_DIR, CONF_DIR}
logAccessConfigStr = strings.Replace(logAccessConfigStr, "{DOCKER_DIR}", DOCKER_DIR, -1)
logConfigStr = strings.Replace(logConfigStr, "{DOCKER_DIR}", DOCKER_DIR, -1)
for _, folder := range FOLDERS </span><span class="cov8" title="1">{
os.MkdirAll(folder, 0775)
}</span>
<span class="cov8" title="1">server = NewServer()
flag.Parse()
peerId := fmt.Sprintf("%d", server.util.RandInt(0, 9))
if !server.util.FileExists(CONST_CONF_FILE_NAME) </span><span class="cov0" title="0">{
peer := "http://" + server.util.GetPulicIP() + ":8080"
cfg := fmt.Sprintf(cfgJson, peerId, peer, peer)
server.util.WriteFile(CONST_CONF_FILE_NAME, cfg)
}</span>
<span class="cov8" title="1">if logger, err := log.LoggerFromConfigAsBytes([]byte(logConfigStr)); err != nil </span><span class="cov0" title="0">{
panic(err)</span>
}<span class="cov8" title="1"> else {
log.ReplaceLogger(logger)
}</span>
<span class="cov8" title="1">if _logacc, err := log.LoggerFromConfigAsBytes([]byte(logAccessConfigStr)); err == nil </span><span class="cov8" title="1">{
logacc = _logacc
log.Info("succes init log access")
}</span><span class="cov0" title="0"> else {
log.Error(err.Error())
}</span>
<span class="cov8" title="1">ParseConfig(CONST_CONF_FILE_NAME)
if Config().QueueSize == 0 </span><span class="cov0" title="0">{
Config().QueueSize = CONST_QUEUE_SIZE
}</span>
<span class="cov8" title="1">if Config().PeerId == "" </span><span class="cov0" title="0">{
Config().PeerId = peerId
}</span>
<span class="cov8" title="1">staticHandler = http.StripPrefix("/"+Config().Group+"/", http.FileServer(http.Dir(STORE_DIR)))
server.initComponent(false)</span>
}
func (this *Server) test() <span class="cov0" title="0">{
testLock := func() </span><span class="cov0" title="0">{
tt := func(i int) </span><span class="cov0" title="0">{
if server.lockMap.IsLock("xx") </span><span class="cov0" title="0">{
return
}</span>
<span class="cov0" title="0">server.lockMap.LockKey("xx")
defer server.lockMap.UnLockKey("xx")
//time.Sleep(time.Nanosecond*1)
fmt.Println("xx", i)</span>
}
<span class="cov0" title="0">for i := 0; i &lt; 10000; i++ </span><span class="cov0" title="0">{
go tt(i)
}</span>
<span class="cov0" title="0">time.Sleep(time.Second * 3)
go tt(999999)
go tt(999999)
go tt(999999)</span>
}
<span class="cov0" title="0">_ = testLock
testFile := func() </span><span class="cov0" title="0">{
var (
err error
f *os.File
)
f, err = os.OpenFile("tt", os.O_CREATE|os.O_RDWR, 0777)
if err != nil </span><span class="cov0" title="0">{
fmt.Println(err)
}</span>
<span class="cov0" title="0">f.WriteAt([]byte("1"), 100)
f.Seek(0, 2)
f.Write([]byte("2"))</span>
//fmt.Println(f.Seek(0, 2))
//fmt.Println(f.Seek(3, 2))
//fmt.Println(f.Seek(3, 0))
//fmt.Println(f.Seek(3, 1))
//fmt.Println(f.Seek(3, 0))
//f.Write([]byte("1"))
}
<span class="cov0" title="0">_ = testFile</span>
//testFile()
}
func (this *Server) initTus() <span class="cov8" title="1">{
var (
err error
fileLog *os.File
bigDir string
)
BIG_DIR := STORE_DIR + "/_big/" + Config().PeerId
os.MkdirAll(BIG_DIR, 0775)
os.MkdirAll(LOG_DIR, 0775)
store := filestore.FileStore{
Path: BIG_DIR,
}
if fileLog, err = os.OpenFile(LOG_DIR+"/tusd.log", os.O_CREATE|os.O_RDWR, 0666); err != nil </span><span class="cov0" title="0">{
log.Error(err)
fmt.Println(err)
panic("initTus")</span>
}
<span class="cov8" title="1">go func() </span><span class="cov8" title="1">{
for </span><span class="cov8" title="1">{
if fi, err := fileLog.Stat(); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span><span class="cov8" title="1"> else {
if fi.Size() &gt; 1024*1024*500 </span><span class="cov0" title="0">{ //500M
this.util.CopyFile(LOG_DIR+"/tusd.log", LOG_DIR+"/tusd.log.2")
fileLog.Seek(0, 0)
fileLog.Truncate(0)
fileLog.Seek(0, 2)
}</span>
}
<span class="cov8" title="1">time.Sleep(time.Second * 30)</span>
}
}()
<span class="cov8" title="1">l := slog.New(fileLog, "[tusd] ", slog.LstdFlags)
bigDir = CONST_BIG_UPLOAD_PATH_SUFFIX
if Config().SupportGroupManage </span><span class="cov0" title="0">{
bigDir = fmt.Sprintf("/%s%s", Config().Group, CONST_BIG_UPLOAD_PATH_SUFFIX)
}</span>
<span class="cov8" title="1">composer := tusd.NewStoreComposer()
// support raw tus upload and download
store.GetReaderExt = func(id string) (io.Reader, error) </span><span class="cov8" title="1">{
var (
offset int64
err error
length int
buffer []byte
fi *FileInfo
)
if fi, err = this.GetFileInfoFromLevelDB(id); err != nil </span><span class="cov0" title="0">{
log.Error(err)
return nil, err
}</span><span class="cov8" title="1"> else {
fp := DOCKER_DIR + fi.Path + "/" + fi.ReName
if this.util.FileExists(fp) </span><span class="cov8" title="1">{
log.Info(fmt.Sprintf("download:%s", fp))
return os.Open(fp)
}</span>
<span class="cov8" title="1">ps := strings.Split(fp, ",")
if len(ps) &gt; 2 &amp;&amp; this.util.FileExists(ps[0]) </span><span class="cov8" title="1">{
if length, err = strconv.Atoi(ps[2]); err != nil </span><span class="cov0" title="0">{
return nil, err
}</span>
<span class="cov8" title="1">if offset, err = strconv.ParseInt(ps[1], 10, 64); err != nil </span><span class="cov0" title="0">{
return nil, err
}</span>
<span class="cov8" title="1">if buffer, err = this.util.ReadFileByOffSet(ps[0], offset, length); err != nil </span><span class="cov0" title="0">{
return nil, err
}</span>
<span class="cov8" title="1">if buffer[0] == '1' </span><span class="cov8" title="1">{
bufferReader := bytes.NewBuffer(buffer[1:])
return bufferReader, nil
}</span><span class="cov0" title="0"> else {
msg := "data no sync"
log.Error(msg)
return nil, errors.New(msg)
}</span>
}
<span class="cov0" title="0">return nil, errors.New(fmt.Sprintf("%s not found", fp))</span>
}
}
<span class="cov8" title="1">store.UseIn(composer)
handler, err := tusd.NewHandler(tusd.Config{
Logger: l,
BasePath: bigDir,
StoreComposer: composer,
NotifyCompleteUploads: true,
})
notify := func(handler *tusd.Handler) </span><span class="cov8" title="1">{
for </span><span class="cov8" title="1">{
select </span>{
case info := &lt;-handler.CompleteUploads:<span class="cov8" title="1">
log.Info("CompleteUploads", info)
name := ""
if v, ok := info.MetaData["filename"]; ok </span><span class="cov8" title="1">{
name = v
}</span>
<span class="cov8" title="1">var err error
md5sum := ""
oldFullPath := BIG_DIR + "/" + info.ID + ".bin"
infoFullPath := BIG_DIR + "/" + info.ID + ".info"
if md5sum, err = this.util.GetFileSumByName(oldFullPath, Config().FileSumArithmetic); err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov8" title="1">ext := path.Ext(name)
filename := md5sum + ext
timeStamp := time.Now().Unix()
fpath := time.Now().Format("/20060102/15/04/")
newFullPath := STORE_DIR + "/" + Config().DefaultScene + fpath + Config().PeerId + "/" + filename
if fi, err := this.GetFileInfoFromLevelDB(md5sum); err != nil </span><span class="cov8" title="1">{
log.Error(err)
}</span><span class="cov8" title="1"> else {
if fi.Md5 != "" </span><span class="cov8" title="1">{
if _, err := this.SaveFileInfoToLevelDB(info.ID, fi); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
<span class="cov8" title="1">log.Info(fmt.Sprintf("file is found md5:%s", fi.Md5))
log.Info("remove file:", oldFullPath)
log.Info("remove file:", infoFullPath)
os.Remove(oldFullPath)
os.Remove(infoFullPath)
continue</span>
}
}
<span class="cov8" title="1">fpath = STORE_DIR_NAME + "/" + Config().DefaultScene + fpath + Config().PeerId
os.MkdirAll(fpath, 0775)
fileInfo := &amp;FileInfo{
Name: name,
Path: fpath,
ReName: filename,
Size: info.Size,
TimeStamp: timeStamp,
Md5: md5sum,
Peers: []string{this.host},
OffSet: -1,
}
if err = os.Rename(oldFullPath, newFullPath); err != nil </span><span class="cov0" title="0">{
log.Error(err)
continue</span>
}
<span class="cov8" title="1">os.Remove(infoFullPath)
this.postFileToPeer(fileInfo)
this.SaveFileInfoToLevelDB(info.ID, fileInfo) //add fileId to ldb
this.SaveFileMd5Log(fileInfo, CONST_FILE_Md5_FILE_NAME)</span>
}
}
}
<span class="cov8" title="1">go notify(handler)
if err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span>
<span class="cov8" title="1">http.Handle(bigDir, http.StripPrefix(bigDir, handler))</span>
}
func (this *Server) FormatStatInfo() <span class="cov8" title="1">{
var (
data []byte
err error
count int64
stat map[string]interface{}
)
if this.util.FileExists(CONST_STAT_FILE_NAME) </span><span class="cov8" title="1">{
if data, err = this.util.ReadBinFile(CONST_STAT_FILE_NAME); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span><span class="cov8" title="1"> else {
if err = json.Unmarshal(data, &amp;stat); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span><span class="cov8" title="1"> else {
for k, v := range stat </span><span class="cov8" title="1">{
switch v.(type) </span>{
case float64:<span class="cov8" title="1">
vv := strings.Split(fmt.Sprintf("%f", v), ".")[0]
if count, err = strconv.ParseInt(vv, 10, 64); err != nil </span><span class="cov0" title="0">{
log.Error(err)
}</span><span class="cov8" title="1"> else {
this.statMap.Put(k, count)
}</span>
default:<span class="cov0" title="0">
this.statMap.Put(k, v)</span>
}
}
}
}
}<span class="cov0" title="0"> else {
this.RepairStat()
}</span>
}
func (this *Server) initComponent(isReload bool) <span class="cov8" title="1">{
var (
ip string
)
ip = this.util.GetPulicIP()
if Config().Host == "" </span><span class="cov0" title="0">{
if len(strings.Split(Config().Addr, ":")) == 2 </span><span class="cov0" title="0">{
server.host = fmt.Sprintf("http://%s:%s", ip, strings.Split(Config().Addr, ":")[1])
Config().Host = server.host
}</span>
}<span class="cov8" title="1"> else {
server.host = Config().Host
}</span>
<span class="cov8" title="1">ex, _ := regexp.Compile("\\d+\\.\\d+\\.\\d+\\.\\d+")
var peers []string
for _, peer := range Config().Peers </span><span class="cov8" title="1">{
if this.util.Contains(ip, ex.FindAllString(peer, -1)) ||
this.util.Contains("127.0.0.1", ex.FindAllString(peer, -1)) </span><span class="cov0" title="0">{
continue</span>
}
<span class="cov8" title="1">if strings.HasPrefix(peer, "http") </span><span class="cov8" title="1">{
peers = append(peers, peer)
}</span><span class="cov0" title="0"> else {
peers = append(peers, "http://"+peer)
}</span>
}
<span class="cov8" title="1">Config().Peers = peers
if !isReload </span><span class="cov8" title="1">{
this.FormatStatInfo()
this.initTus()
}</span>
//Timer
// int tus
}
type HttpHandler struct {
}
func (HttpHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) <span class="cov8" title="1">{
status_code := "200"
defer func(t time.Time) </span><span class="cov8" title="1">{
logStr := fmt.Sprintf("[Access] %s | %v | %s | %s | %s | %s |%s",
time.Now().Format("2006/01/02 - 15:04:05"),
res.Header(),
time.Since(t).String(),
server.util.GetClientIp(req),
req.Method,
status_code,
req.RequestURI,
)
logacc.Info(logStr)
}</span>(time.Now())
<span class="cov8" title="1">defer func() </span><span class="cov8" title="1">{
if err := recover(); err != nil </span><span class="cov0" title="0">{
status_code = "500"
res.WriteHeader(500)
print(err)
buff := debug.Stack()
log.Error(err)
log.Error(string(buff))
}</span>
}()
<span class="cov8" title="1">http.DefaultServeMux.ServeHTTP(res, req)</span>
}
func (this *Server) Main() <span class="cov8" title="1">{
go func() </span><span class="cov8" title="1">{
for </span><span class="cov8" title="1">{
this.CheckFileAndSendToPeer(this.util.GetToDay(), CONST_Md5_ERROR_FILE_NAME, false)
//fmt.Println("CheckFileAndSendToPeer")
time.Sleep(time.Second * time.Duration(Config().RefreshInterval))
//this.util.RemoveEmptyDir(STORE_DIR)
}</span>
}()
<span class="cov8" title="1">go this.CleanMd5SumCache()
go this.Check()
go this.Consumer()
go this.ConsumerDownLoad()
if Config().AutoRepair </span><span class="cov8" title="1">{
go func() </span><span class="cov8" title="1">{
for </span><span class="cov8" title="1">{
time.Sleep(time.Minute * 3)
this.AutoRepair(false)
time.Sleep(time.Minute * 60)
}</span>
}()
}
<span class="cov8" title="1">if Config().SupportGroupManage </span><span class="cov0" title="0">{
http.HandleFunc(fmt.Sprintf("/%s", Config().Group), this.Index)
http.HandleFunc(fmt.Sprintf("/%s/check_file_exist", Config().Group), this.CheckFileExist)
http.HandleFunc(fmt.Sprintf("/%s/upload", Config().Group), this.Upload)
http.HandleFunc(fmt.Sprintf("/%s/delete", Config().Group), this.RemoveFile)
http.HandleFunc(fmt.Sprintf("/%s/sync", Config().Group), this.Sync)
http.HandleFunc(fmt.Sprintf("/%s/stat", Config().Group), this.Stat)
http.HandleFunc(fmt.Sprintf("/%s/repair_stat", Config().Group), this.RepairStatWeb)
http.HandleFunc(fmt.Sprintf("/%s/status", Config().Group), this.Status)
http.HandleFunc(fmt.Sprintf("/%s/repair", Config().Group), this.Repair)
http.HandleFunc(fmt.Sprintf("/%s/repair_fileinfo", Config().Group), this.RepairFileInfo)
http.HandleFunc(fmt.Sprintf("/%s/reload", Config().Group), this.Reload)
http.HandleFunc(fmt.Sprintf("/%s/syncfile_info", Config().Group), this.SyncFileInfo)
http.HandleFunc(fmt.Sprintf("/%s/get_md5s_by_date", Config().Group), this.GetMd5sForWeb)
http.HandleFunc(fmt.Sprintf("/%s/receive_md5s", Config().Group), this.ReceiveMd5s)
}</span><span class="cov8" title="1"> else {
http.HandleFunc("/", this.Index)
http.HandleFunc("/check_file_exist", this.CheckFileExist)
http.HandleFunc("/upload", this.Upload)
http.HandleFunc("/delete", this.RemoveFile)
http.HandleFunc("/sync", this.Sync)
http.HandleFunc("/stat", this.Stat)
http.HandleFunc("/repair_stat", this.RepairStatWeb)
http.HandleFunc("/status", this.Status)
http.HandleFunc("/repair", this.Repair)
http.HandleFunc("/repair_fileinfo", this.RepairFileInfo)
http.HandleFunc("/reload", this.Reload)
http.HandleFunc("/syncfile_info", this.SyncFileInfo)
http.HandleFunc("/get_md5s_by_date", this.GetMd5sForWeb)
http.HandleFunc("/receive_md5s", this.ReceiveMd5s)
}</span>
<span class="cov8" title="1">http.HandleFunc("/"+Config().Group+"/", this.Download)
fmt.Println("Listen on " + Config().Addr)
err := http.ListenAndServe(Config().Addr, new(HttpHandler))
log.Error(err)
fmt.Println(err)</span>
}
func main() <span class="cov8" title="1">{
server.Main()
}</span>
</pre>
</div>
</body>
<script>
(function() {
var files = document.getElementById('files');
var visible;
files.addEventListener('change', onChange, false);
function select(part) {
if (visible)
visible.style.display = 'none';
visible = document.getElementById(part);
if (!visible)
return;
files.value = part;
visible.style.display = 'block';
location.hash = part;
}
function onChange() {
select(files.value);
window.scrollTo(0, 0);
}
if (location.hash != "") {
select(location.hash.substr(1));
}
if (!visible) {
select("file0");
}
})();
</script>
</html>