//run service func (this *CsvInput) Run() { log.Infoln("CsvInput is starting") log.Infof("open file %s", this.Config.FileName) g := float64(this.Config.Period) if bts, err := ioutil.ReadFile(this.Config.FileName); err == nil { strs := strings.Split(string(bts), "\n") for common.IsRun { beginget := time.Now() mod := this.TIME.Minute() % 3 // log.Infof("w count is %d", mod+1) for i := 0; i <= mod; i++ { row := new(common.DataRows) row.Time = time.Now().Format(this.Config.TimeFormat) row.RowMap = this.RowMap for _, str := range strs { if this.Config.OutputColumn == nil { log.Infoln("output column is nil") break } cols := strings.Split(str, ",") var r []interface{} for _, c := range cols { if d, err := strconv.ParseFloat(c, 10); err == nil { r = append(r, d) } else { r = append(r, 0) } } row.Rows = append(row.Rows, r) } this.Output <- row //log.Infof("push row is %v", row.Time) } //计算下一次运行的时间 this.TIME = this.TIME.Add(time.Minute * time.Duration(g)) log.Infof("next time is %v", this.TIME) sec := time.Since(beginget).Seconds() //计算下一次运行的时间 if sec < g*60 { //如果一个处理周期内处理完,就延时,没有处理完就立即执行,如果正式运行期间还需要进行时间纠正 log.Infof("sleep seconds %f", (g*60)-sec) time.Sleep(time.Second * (time.Duration(g*60 - sec))) //sleep one minute-sec } } } else { log.Error(err.Error()) } close(this.Output) }
//执行带参数的特定id的sql,并返回数据 func BySqlParamName(id string, p map[string]interface{}) (map[string]int, [][]interface{}, error) { if client, err := rpc.DialHTTP("tcp", fmt.Sprintf("%s:%d", ServerIP, Port)); err != nil { var reply = new(common.RPCResponseSql) args := common.RPCRequestSql{Id: id, Param: p} err = client.Call("Oracle.BySqlParamName", args, &reply) if err != nil { log.Error("bysql error:", err) } return reply.Cols, reply.Rows, err } else { log.Errorf("rcp %s:%d error", ServerIP, Port, err.Error()) } return nil, nil, fmt.Errorf("sql %s not exists", id) }
//数据库write操作 func pid4(cmd *common.RequestData, c *online.Client) { if checkParamError(cmd, c, "Id", "Param") { return } id := cmd.GetString("Id") m := make(map[string]interface{}) err := rpc.ExecSqlParamName(id, m) if err != nil { log.Error(err.Error()) writePrror("db error", cmd, c) return } writepid(c, cmd, 0, nil) }
//处理单元入口 func GetData(dp *common.DataParam, t time.Time) *common.OutputParam { if dp.TimeRange == 1 && len(dp.LimitId) == 1 { //单网元,单时间点,用于指标详细 log.Infoln("开始处理过程,单网元,单时间点,用于指标详细") return GetColumnsData(dp, t) } else if dp.TimeRange > 1 && len(dp.LimitId) == 1 { //单网元,多时间点,用于走势图 log.Infoln("开始处理过程,单网元,多时间点,用于走势图") return GetTimeLineData(dp, t) } else if dp.TimeRange == 1 && (len(dp.LimitId) > 1 || len(dp.LimitNodeId) > 0) { //单时间点,多网元,用于排行榜 log.Infoln("开始处理过程,单时间点,多网元,用于排行榜") return GetOrderData(dp, t) } else { //多时间点,多网元,暂不支持 log.Error("开始处理过程,不被支持的过程", dp.ToString()) return nil } }
//将数据保存到外部缓存中,同时也支持从外部缓存取数据,在这里进行屏蔽,其它地方不操作外部缓存 //保存到外部存贮 func saveToStore(key string, value *common.DataRow, expired int) { //begin := time.Now() if len(pool) > 0 { if c, err := GetClient(value.Time); err == nil { defer c.Close() if bs, err := encode(*value); err == nil { c.Redis.Hset(key, value.Time, bs) c.Redis.Expire(key, int64(expired*60)) //秒 } } else { log.Error("get client error,begin recycle", err.Error()) //回收连接,过段时间再试 } } //diff := time.Since(begin) //log.Infof("save to store at %v seconds", diff.Seconds()) }
//数据库read操作 func pid3(cmd *common.RequestData, c *online.Client) { if checkParamError(cmd, c, "Id", "Param") { return } id := cmd.GetString("Id") m := make(map[string]interface{}) col, rows, err := rpc.BySqlParamName(id, m) if err != nil { log.Error(err.Error()) writePrror("db error", cmd, c) return } dp := new(common.OutputParam) dp.RowMap = col dp.Rows = rows dp.Time = time.Now() writepid(c, cmd, 0, dp) }
//运行计算 func (this *TimeCache) Run() { log.Infoln("cache is started", this.Id) period := 1 if p, ok := Get(FormatKey("System", "Period", this.Id)); ok { period = compute.AsInt(p) } timeFormat := common.GetTimeFormat(period) for rs := range this.input { //接收数据 //log.Infof("time changed ", rs.Time) currTime, err := time.Parse(timeFormat, rs.Time) if err != nil { log.Error("cache time format is error", err.Error()) currTime = time.Now() } cacheItem, ok := this.caches[rs.Time] //这个时间点是否已记录 if !ok { cacheItem = &TimeCacheItem{Cache: make(map[string]interface{})} this.caches[rs.Time] = cacheItem cacheItem.ExpiredTime = time.Now().Add(time.Minute * common.StoreMinute) } for _, vs := range rs.Rows { //分析每一条数据 row := rs.CreateDataRow(vs) key := row.GetKey(this.KeyName) //log.Infoln("add to cache", key) this.lock.Lock() if r, ok := cacheItem.Cache[key]; ok { //如果同类数据已存在,就进行数据合并 row.Merge(r.(*common.DataRow).Row) } cacheItem.Cache[key] = row this.lock.Unlock() //log.Infoln(key, row.Row) // log.Info("key=%s", key) go saveToStore(FormatStoreKey(this.Id, key), row, period*common.StoreCount) //保存到外部存贮,并保存粒度*保存个数分钟 } //通知外到有新数据到来 if TimeChanged != nil { TimeChanged(&common.TimeMessage{Key: this.Id, Time: currTime}) } } }
// login in func pid_1(cmd *common.RequestData, c *online.Client) { if checkParamError(cmd, c, "Login", "Password") { return } login := cmd.GetString("Login") pwd := cmd.GetString("Password") c.Name = login log.Infof("user %s login", c.Name, common.IsDebug) loginSuccess := false if common.IsDebug { //调试时直接登陆,不验证密码 loginSuccess = true } else { param := make(map[string]interface{}) param["login"] = login _, epwd, err := rpc.BySqlParamName("login", param) if err != nil { log.Error(err.Error()) } if err == nil && len(epwd) > 0 { loginSuccess = epwd[0][0] == pwd //需要对密码进行加密再进行比较 } } //check re := make(map[string]interface{}) if loginSuccess { c.IsLogin = true c.Key = common.HashString(c.UUID + ":" + c.Name) online.SetSession(c.UUID, c.Name, c.Key) re["LoginState"] = 0 re["Message"] = "login success" re["UID"] = c.UUID re["Key"] = c.Key online.Set(c) } else { re["LoginState"] = -1 re["Message"] = "login failed" } writepid(c, cmd, 0, re) }
//read cmd from byte func (this *Client) Read(data []byte, cmd *common.RequestData) { if err := json.Unmarshal(data, cmd); err != nil { log.Error("cmd format error,cmd string is %s,error is %s", string(data), err.Error()) } }
//处理单独的Http请求 func (this *HttpService) HandleHttp(w http.ResponseWriter, req *http.Request) { req.ParseForm() uid := req.Header.Get(Sec_Auth_Uid) key := req.Header.Get(Sec_Auth_Key) c := this.getClient(uid, key) defer c.Close() if data := req.FormValue("json"); len(data) > 0 { cmd := new(common.RequestData) c.Read([]byte(data), cmd) protocol.Exec(cmd, &c.Client) } else { cmd := common.ResponseData{0, -1, "json string is empty", ""} c.Send(&cmd) } for { timeout := time.After(time.Nanosecond * 10) //10ns就超时 select { case data := <-c.OutputChan: if _, err := w.Write(data); err != nil { log.Error("%s send cmd error and login out,%s\n", c.Name, err.Error()) } break case <-timeout: goto end } } end: } //按cookei取在线用户 func (this *HttpService) getClient(uid string, key string) *HttpClient { c := new(HttpClient) if s, _, ok := online.GetSession(uid); ok && s == key { //key相同时认为已登陆过的 if tc, ok := online.Get(uid); ok { //第一个登陆的Client的uuid被当作了uid c.Name = tc.Name c.IsLogin = tc.IsLogin c.IsPlayBack = c.IsPlayBack } } if c == nil { c = new(HttpClient) } c.UUID = uuid.New() c.IsRun = true c.OutputChan = make(chan []byte, 10) return c } ////设置cookie //func (this *HttpService) setCookie(c *HttpClient, w http.ResponseWriter, age int) { // id := &http.Cookie{Name: "monitor_http_key", Value: common.HashString(c.Name + ":monitor"), Path: "/", MaxAge: age, HttpOnly: true, Secure: true} // name := &http.Cookie{Name: "monitor_http_name", Value: c.Name, Path: "/", MaxAge: age, HttpOnly: true, Secure: true} // http.SetCookie(w, id) // http.SetCookie(w, name) //} //处理Socket请求 func (this *HttpService) HandleSocket(ws *websocket.Conn) { connFrom := ws.RemoteAddr() log.Infof("accept new http client from %s\n", connFrom) uid := ws.Request().Header.Get(Sec_Auth_Uid) key := ws.Request().Header.Get(Sec_Auth_Key) c := this.getClient(uid, key) c.Connect = ws go this.HandleResponse(c) this.HandleRequest(c) } //主运行方法 //根目录为标准Http请求 //socket为Socket请求 func (this *HttpService) Run() { this.IsRun = true http.Handle("/", http.FileServer(http.Dir("."))) // <-- note this line http.HandleFunc("/http", this.HandleHttp) http.Handle("/socket", websocket.Handler(this.HandleSocket)) log.Infof("http service started at %s:%d", this.Host, this.Port) log.Info("http socket host on /http and /socket ") if err := http.ListenAndServe(fmt.Sprintf("%s:%d", this.Host, this.Port), nil); err != nil { log.Error("http service start error", err.Error()) } } //send cmd to client func (this *HttpService) HandleResponse(c *HttpClient) { var err error defer online.Delete(c.UUID) for cmd := range c.OutputChan { //cmd := <-c.OutputChan cmd = append(cmd, '\n') if err = websocket.Message.Send(c.Connect, string(cmd)); err != nil { log.Error("%s send cmd error and login out,%s\n", c.Name, err.Error()) c.IsRun = false break } c.UpdateTime() } } //handle tcp request func (this *HttpService) HandleRequest(c *HttpClient) { var err error defer online.Delete(c.UUID) cmd := new(common.RequestData) var data []byte for this.IsRun && c.IsRun { if err = websocket.Message.Receive(c.Connect, &data); err != nil { log.Infof("%s can't received cmd", c.Name, err.Error()) c.IsRun = false break } c.Read(data, cmd) protocol.Exec(cmd, &c.Client) c.UpdateTime() } }