func (s *Server) mkChServer(conn InstConn, args []reflect.Value, enc *msgpack.Encoder) (err error) { typeChanDesc := reflect.TypeOf(&ChannelDescriptor{}) for i, arg := range args { if arg.Type() != typeChanDesc { continue } chd := arg.Interface().(*ChannelDescriptor) // criar channel. Value ch := chd.Make(true) // substituir o ChannelDescriptor pelo channel criado args[i] = ch // criar sessão/instância instname, err := rand.Chars(16, rand.NumberLetters, "go") if err != nil { return e.Forward(err) } owners := auth.NewPlainTextCredentials() err = owners.Add(conn.Auth()) if err != nil { return e.Forward(err) } err = s.Insts.NewChValueInstance(conn.SessionName(), instname, ch, chd.Dir, owners) if err != nil { return e.Forward(err) } // envia-las err = enc.Encode(instname) if err != nil { return e.Forward(err) } } return nil }
func (vs *VirtualServer) SendToQueue(f interface{}, args ...interface{}) error { rnd, err := rand.Chars(10, rand.NumberLetters, "go") if err != nil { return e.Forward(err) } job := job.NewSimple(vs.VirtualServerName+rnd, vs.Prio, f, args...) vs.status.Log(status.Verbose, "Add job %v for %v to queue %v.", job.Name(), vs.VirtualServerName, vs.Prio) err = vs.Queue.Add(job) if err != nil { return e.Forward(err) } vs.status.Log(status.Verbose, "Waiting job %v return.", job.Name()) job.Returns(&err) if err != nil { return e.Forward(err) } vs.status.Log(status.Verbose, "Job %v returned.", job.Name()) return nil }
func (p *protoServer) newInst(sess string, a auth.Auth, obj string, args ...interface{}) (string, error) { val, err := p.Cons.Construct(obj, args...) if err != nil { return "", e.Forward(err) } inst, err := rand.Chars(16, rand.NumberLetters, "go") if err != nil { return "", e.Forward(err) } owners := auth.NewPlainTextCredentials() err = owners.Add(a) if err != nil { return "", e.Forward(err) } err = p.Insts.New(sess, inst, val, owners) if err != nil { return "", e.Forward(err) } return inst, nil }
func (d *Daemon) monitor() { go func() { d.monitoring = true var tries int unmonitor := true F: for { select { case <-time.After(d.Sleep): if d.Tries != 0 && tries > d.Tries+1 { d.monitoring = false if unmonitor { d.status.LogAndEmail(status.Normal, "", "Unmonitor daemon %v.", d.DaemonName) unmonitor = false continue F } continue F } d.changePid() if d.pid == -1 { d.status.LogAndEmail(status.Normal, "", "No pid file %v for %v.", d.PidFile, d.DaemonName) d.running = false } else { err := syscall.Kill(d.pid, 0) if err != nil && err.Error() == "no such process" { d.status.LogAndEmail(status.Normal, "", "%v process is gone.", d.DaemonName) d.running = false } else if err != nil { d.status.Log(status.Verbose, "Monitor failed for %v with error: %v", d.DaemonName, e.Trace(e.New(err))) d.running = false } else { d.running = true } } if d.running { err := d.ping() if e.Equal(err, ErrPingFailed) { d.running = false } else if err != nil && !e.Equal(err, ErrProtoNotSupported) && !e.Equal(err, ErrUrlIsEmpty) { d.status.Log(status.Verbose, "Monitor ping failed for %v with error: %v", d.DaemonName, e.Trace(e.Forward(err))) d.running = false } p, err := event.ProbeProcess(d.pid) if e.Equal(err, "process not found") { d.status.LogAndEmail(status.Normal, "", "%v process is gone.", d.DaemonName) d.running = false } else if err != nil { d.status.Log(status.Verbose, "ProbeCurrentProcess failed with error: %v", err) } else { d.SendEvent(p) } } if !d.running { tries++ rnd, err := rand.Chars(10, rand.NumberLetters, "go") if err != nil { d.status.Log(status.Verbose, "Can't generate the job name for %v. Error: %v", d.DaemonName, e.Trace(e.Forward(err))) continue } job := job.NewSimple(d.DaemonName+rnd, d.Prio, func() error { err := d.restartProcess() if err != nil { d.status.LogAndEmail(status.Normal, "", "Can't restart process %v.", d.DaemonName) return e.Forward(err) } return nil }) d.status.Log(status.Verbose, "Add job %v for %v to queue %v.", job.Name(), d.DaemonName, d.Prio) d.Queue.Add(job) d.status.Log(status.Verbose, "Waiting job %v return.", job.Name()) job.Returns(&err) if err != nil { continue } d.status.LogAndEmail(status.Normal, "", "Restart command sent to %v.", d.DaemonName) } else { d.status.Log(status.Verbose, "%v process is running.", d.DaemonName) tries = 0 } case <-d.killMonitor: d.status.Log(status.Normal, "Monitor %v stopped.", d.DaemonName) return } } }() }
func MakeFile(pkg, pkgout, src string, debug bool) (*File, error) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, "", src, parser.ParseComments) if err != nil { return nil, e.New(err) } v := &Visitor{ src: src, Struct: make(map[string]*Strct), Cmap: ast.NewCommentMap(fset, f, f.Comments), StructOrder: make([]*Strct, 0), Pkgs: NewPkgs(), } v.Pkgs.Have("crypto/tls") v.Pkgs.Have("fmt") v.Pkgs.Have("log") v.Pkgs.Have("reflect") v.Pkgs.Have("tls") v.Pkgs.Have("time") v.Pkgs.Have("github.com/fcavani/e") v.Pkgs.Have("github.com/fcavani/gormethods/auth") v.Pkgs.Have("github.com/fcavani/gormethods/client") v.Pkgs.Have("gopkg.in/vmihailenco/msgpack.v2") ast.Walk(v, f) file := &File{ Package: f.Name.Name, Debug: debug, PkgComplete: f.Name.Name, Pkgs: v.Pkgs.Packages(), } if pkg != "" { file.PkgComplete = pkg } if pkgout != "" { file.Package = pkgout } objs := make(map[string]*Object) order := make([]string, 0) for _, f := range v.Functions { u := utf8string.NewString(f.RecvType) if u.RuneCount() > 0 && !unicode.IsUpper(u.At(0)) { continue } if f.RecvType == "" { continue } if FuncForbiden(f.Name) { continue } obj, found := objs[f.RecvType] if !found { function, err := makeFunction(f) if err != nil { return nil, e.Forward(err) } t := f.RecvType if f.PtrRecv { t = "*" + t } strct, found := v.Struct[f.RecvType] if !found { return nil, e.New("struct %v not found", f.RecvType) } objs[f.RecvType] = &Object{ Name: f.RecvType, NameClient: f.RecvType + "Client", RecvVar: f.Recv, RecvType: t, Functions: []*Function{function}, Type: makeType(src, strct.Type), Comments: strings.Replace(strct.Comments, f.RecvType, f.RecvType+"Client", -1), } v.Struct[f.RecvType].FunctionCount++ order = append(order, f.RecvType) } else { function, err := makeFunction(f) if err != nil { return nil, e.Forward(err) } obj.Functions = append(obj.Functions, function) } } for _, s := range v.StructOrder { if s.FunctionCount == 0 { first, err := rand.Chars(1, rand.Letters, "go") if err != nil { return nil, e.Push(err, "can't create a name to the receiver for the struct") } recv, err := rand.Chars(2, rand.NumberLetters, "go") if err != nil { return nil, e.Push(err, "can't create a name to the receiver for the struct") } recv = strings.ToLower(first + recv) objs[s.Name] = &Object{ Name: s.Name, NameClient: s.Name + "Client", RecvVar: recv, RecvType: s.Name, Functions: nil, Type: makeType(src, s.Type), Comments: strings.Replace(s.Comments, s.Name, s.Name+"Client", -1), } } } for _, s := range v.StructOrder { if obj, found := objs[s.Name]; found { file.Objects = append(file.Objects, obj) } else { return nil, e.New("object not found: %v", s.Name) } } return file, nil }
func (s *Server) protoCall(conn InstConn) (err error) { enc := conn.Encoder() dec := conn.Decoder() defer func() { if err != nil { err = enc.Encode(&respCall{Err: err}) if err != nil { log.ProtoLevel().Tag("server", "gormethods").Printf("Encode %v -> %v (%v) error: %v", conn.RemoteAddr(), conn.LocalAddr(), conn.StreamNum(), err) err = e.Push(err, ErrWire) } } }() inst, err := s.Insts.Get(conn.SessionName(), conn.InstanceName()) if err != nil { log.Tag("server", "gormethods").Errorf("Error getting the instance %v/%v: %v", conn.SessionName(), conn.InstanceName(), e.Forward(err)) err = e.Forward(err) return } if inst.Type() != WithValue { log.Tag("server", "gormethods").Errorf("Instance %v/%v is of wrong type", conn.SessionName(), conn.InstanceName()) return e.New("instance is of wrong type") } log.ProtoLevel().Tag("gormethods", "server", "call").Printf("Call %v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type())) var req reqCall err = dec.Decode(&req) if e.Find(err, io.EOF) >= 0 { return e.Push(err, ErrWire) } else if err != nil { log.ProtoLevel().Tag("server", "gormethods").Printf("Decode %v -> %v (%v) error: %v", conn.RemoteAddr(), conn.LocalAddr(), conn.StreamNum(), err) err = e.Push(err, ErrWire) return } // Tratar argumentos (req.Args) com channel // criar channel // recebe do channel envia pelo conn // recebe do conn envia para channel // (faz isso até fechar o channel em um dos lados) // substutui em req.Args os channels // Se existem channels enviar instancias err = s.mkChServer(conn, req.Args, enc) if err != nil { err = e.Forward(err) log.Tag("server", "gormethods").Errorf("Channel arguments setup failed: %v", err) return } method := inst.Instance().MethodByName(req.Method) if !method.IsValid() { err = e.Push(e.New(ErrMethodNotFound), e.New("method %v not found", req.Method)) log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), conn.InstanceName(), err) return } log.ProtoLevel().Tag("server", "gormethods").Printf("Call %v/%v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type()), req.Method) var retvals []reflect.Value if method.Type().IsVariadic() { retvals = method.CallSlice(req.Args) } else { retvals = method.Call(req.Args) } log.ProtoLevel().Tag("server", "gormethods").Printf("Call returned %v/%v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type()), req.Method) for i := range retvals { var exp *Export exp, err = s.Insts.ExportGet(conn.SessionName(), conn.InstanceName(), req.Method, i) if err != nil { continue } var instname string instname, err = rand.Chars(16, rand.NumberLetters, "go") if err != nil { err = e.Push(err, "can't create the instance name for exported retval") log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), conn.InstanceName(), err) return } owners := auth.NewPlainTextCredentials() err = owners.Add(conn.Auth()) if err != nil { err = e.Push(err, "can't authorize the exported retval") log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), conn.InstanceName(), err) return } err = s.Insts.New(conn.SessionName(), instname, retvals[i], owners) if err != nil { err = e.Push(err, "can't crete the instance for the exported retval") log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), instname, err) return } for _, to := range exp.ToExport { err = s.Insts.Export(conn.SessionName(), instname, to) if err != nil { err = e.Push(err, e.New("can't export %v/%v %v %v %v to %v", conn.SessionName(), instname, to.Method, to.RetvalPos, types.Name(retvals[i].Interface()), types.Name(exp.Client))) log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), conn.InstanceName(), err) return } } exp.Client.Associate(conn.SessionName(), instname, conn.Auth()) retvals[i] = reflect.ValueOf(exp.Client) continue } log.ProtoLevel().Tag("server", "gormethods").Printf("Send returned values %v/%v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type()), req.Method) err = enc.Encode(&respCall{ Vals: retvals, Err: nil, }) if err != nil { log.ProtoLevel().Tag("server", "gormethods").Printf("Encode %v -> %v (%v) error: %v", conn.RemoteAddr(), conn.LocalAddr(), conn.StreamNum(), err) err = e.Push(err, ErrWire) return } log.ProtoLevel().Tag("server", "gormethods").Printf("Send returned values done %v/%v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type()), req.Method) return }