func (c *conn) readResponses() { defer c.close() for { r, err := c.readR() if err != nil { c.clk.Lock() if c.err == nil { c.err = err } c.clk.Unlock() return } if r.ErrCode != nil && *r.ErrCode == proto.Response_REDIRECT { c.redirectAddr = pb.GetString(r.ErrDetail) c.redirected = true } tag := pb.GetInt32(r.Tag) flags := pb.GetInt32(r.Flags) c.cblk.Lock() ch, ok := c.cb[tag] if ok && ch == nil { c.cblk.Unlock() continue } if flags&Done != 0 { c.cb[tag] = nil, false } c.cblk.Unlock() if !ok { log.Printf( "%v unexpected: tag=%d flags=%d rev=%d path=%q value=%v len=%d err_code=%v err_detail=%q", ch, tag, flags, pb.GetInt64(r.Rev), pb.GetString(r.Path), r.Value, pb.GetInt32(r.Len), pb.GetInt32((*int32)(r.ErrCode)), pb.GetString(r.ErrDetail), ) continue } if flags&Valid != 0 { ch <- r } if flags&Done != 0 { close(ch) } } }
func (c *conn) getdir(t *T, tx txn) { path := pb.GetString(t.Path) if g := c.getterFor(t); g != nil { ents, rev := g.Get(path) if rev == store.Missing { c.respond(t, Valid|Done, nil, noEnt) return } if rev != store.Dir { c.respond(t, Valid|Done, nil, notDir) return } sort.SortStrings(ents) offset := int(pb.GetInt32(t.Offset)) if offset < 0 || offset >= len(ents) { c.respond(t, Valid|Done, nil, erange) return } e := ents[offset] c.respond(t, Valid|Done, tx.cancel, &R{Path: &e}) } }
func (c *conn) walk(t *T, tx txn) { pat := pb.GetString(t.Path) glob, err := store.CompileGlob(pat) if err != nil { c.respond(t, Valid|Done, nil, errResponse(err)) return } offset := pb.GetInt32(t.Offset) if offset < 0 { c.respond(t, Valid|Done, nil, erange) return } if g := c.getterFor(t); g != nil { var r R f := func(path, body string, rev int64) (stop bool) { if offset == 0 { r.Path = &path r.Value = []byte(body) r.Rev = &rev return true } offset-- return false } if store.Walk(g, glob, f) { c.respond(t, Set|Valid|Done, nil, &r) } else { c.respond(t, Valid|Done, nil, erange) } } }
func (c *conn) events(t *T) (*Watch, os.Error) { cb, err := c.send(t) if err != nil { return nil, err } evs := make(chan *Event) w := &Watch{evs, c, cb, *t.Tag} go func() { for r := range cb { var ev Event if err := r.err(); err != nil { ev.Err = err } else { ev.Rev = pb.GetInt64(r.Rev) ev.Path = pb.GetString(r.Path) ev.Body = r.Value ev.Flag = pb.GetInt32(r.Flags) } evs <- &ev } close(evs) }() return w, nil }
// referenceValueToKey is the same as protoToKey except the input is a // PropertyValue_ReferenceValue instead of a Reference. func referenceValueToKey(r *pb.PropertyValue_ReferenceValue) (k *Key, err error) { appID := proto.GetString(r.App) for _, e := range r.Pathelement { k = &Key{ kind: proto.GetString(e.Type), stringID: proto.GetString(e.Name), intID: proto.GetInt64(e.Id), parent: k, appID: appID, } if !k.valid() { return nil, ErrInvalidKey } } return }
func (c *conn) watch(t *T, tx txn) { pat := pb.GetString(t.Path) glob, err := store.CompileGlob(pat) if err != nil { c.respond(t, Valid|Done, nil, errResponse(err)) return } var w *store.Watch rev := pb.GetInt64(t.Rev) if rev == 0 { w, err = store.NewWatch(c.s.St, glob), nil } else { w, err = store.NewWatchFrom(c.s.St, glob, rev) } switch err { case nil: // nothing case store.ErrTooLate: c.respond(t, Valid|Done, nil, tooLate) default: c.respond(t, Valid|Done, nil, errResponse(err)) } go func() { defer w.Stop() // TODO buffer (and possibly discard) events for { select { case ev := <-w.C: if closed(w.C) { return } r := R{ Path: &ev.Path, Value: []byte(ev.Body), Rev: &ev.Seqn, } var flag int32 switch { case ev.IsSet(): flag = Set case ev.IsDel(): flag = Del } c.respond(t, Valid|flag, tx.cancel, &r) case <-tx.cancel: c.closeTxn(*t.Tag) return } } }() }
// Create creates a channel and returns a token for use by the client. // The clientID is an appication-provided string used to identify the client. func Create(c appengine.Context, clientID string) (token string, err error) { req := &channel_proto.CreateChannelRequest{ ApplicationKey: &clientID, } resp := &channel_proto.CreateChannelResponse{} err = c.Call(service, "CreateChannel", req, resp, nil) token = proto.GetString(resp.ClientId) return }
// loadMapEntry converts a Property into an entry of an existing Map, // or into an element of a slice-valued Map entry. func loadMapEntry(m Map, k *Key, p *pb.Property) os.Error { var ( result interface{} sliceType reflect.Type ) switch { case p.Value.Int64Value != nil: if p.Meaning != nil && *p.Meaning == pb.Property_GD_WHEN { result = Time(*p.Value.Int64Value) sliceType = reflect.TypeOf([]Time(nil)) } else { result = *p.Value.Int64Value sliceType = reflect.TypeOf([]int64(nil)) } case p.Value.BooleanValue != nil: result = *p.Value.BooleanValue sliceType = reflect.TypeOf([]bool(nil)) case p.Value.StringValue != nil: if p.Meaning != nil && *p.Meaning == pb.Property_BLOB { result = []byte(*p.Value.StringValue) sliceType = reflect.TypeOf([][]byte(nil)) } else if p.Meaning != nil && *p.Meaning == pb.Property_BLOBKEY { result = appengine.BlobKey(*p.Value.StringValue) sliceType = reflect.TypeOf([]appengine.BlobKey(nil)) } else { result = *p.Value.StringValue sliceType = reflect.TypeOf([]string(nil)) } case p.Value.DoubleValue != nil: result = *p.Value.DoubleValue sliceType = reflect.TypeOf([]float64(nil)) case p.Value.Referencevalue != nil: key, err := referenceValueToKey(p.Value.Referencevalue) if err != nil { return err } result = key sliceType = reflect.TypeOf([]*Key(nil)) default: return nil } name := proto.GetString(p.Name) if proto.GetBool(p.Multiple) { var s reflect.Value if x := m[name]; x != nil { s = reflect.ValueOf(x) } else { s = reflect.MakeSlice(sliceType, 0, 0) } s = reflect.Append(s, reflect.ValueOf(result)) m[name] = s.Interface() } else { m[name] = result } return nil }
func (c *CheckResult) stringMap() (smap map[string]string) { smap = map[string]string{ "Hostname": fmt.Sprintf("%s", proto.GetString(c.Hostname)), "ServiceName": fmt.Sprintf("%s", proto.GetString(c.ServiceName)), "Status": fmt.Sprintf("%d", int32((*c.Status))), "CheckPassive": fmt.Sprintf("%d", func() (i int32) { if proto.GetBool(c.CheckPassive) { i = 1 } else { i = 0 } return i }()), "CheckOutput": fmt.Sprintf("%s", strings.Trim(strconv.Quote(proto.GetString(c.CheckOutput)), "\"")), "StartTimestamp": fmt.Sprintf("%f", float64(proto.GetInt64(c.StartTimestamp))/1000000000), "EndTimestamp": fmt.Sprintf("%f", float64(proto.GetInt64(c.EndTimestamp))/1000000000), "TimeNow": fmt.Sprintf("%d", time.Seconds()), } return smap }
// protoToRecord converts a RequestLog, the internal Protocol Buffer // representation of a single request-level log, to a Record, its // corresponding external representation. func protoToRecord(rl *log_proto.RequestLog) *Record { return &Record{ AppID: *rl.AppId, VersionID: *rl.VersionId, RequestID: *rl.RequestId, IP: *rl.Ip, Nickname: proto.GetString(rl.Nickname), StartTime: *rl.StartTime, EndTime: *rl.EndTime, Latency: *rl.Latency, MCycles: *rl.Mcycles, Method: *rl.Method, Resource: *rl.Resource, HTTPVersion: *rl.HttpVersion, Status: *rl.Status, ResponseSize: *rl.ResponseSize, Referrer: proto.GetString(rl.Referrer), UserAgent: proto.GetString(rl.UserAgent), URLMapEntry: *rl.UrlMapEntry, Combined: *rl.Combined, APIMCycles: proto.GetInt64(rl.ApiMcycles), Host: proto.GetString(rl.Host), Cost: proto.GetFloat64(rl.Cost), TaskQueueName: proto.GetString(rl.TaskQueueName), TaskName: proto.GetString(rl.TaskName), WasLoadingRequest: proto.GetBool(rl.WasLoadingRequest), PendingTime: proto.GetInt64(rl.PendingTime), Finished: proto.GetBool(rl.Finished), AppLogs: protoToAppLogs(rl.Line), } }
// loadStruct converts an EntityProto into an existing struct. // It returns an error if the destination struct is unable to hold the entity. func loadStruct(sv reflect.Value, k *Key, e *pb.EntityProto) os.Error { var fieldName, reason string for _, p := range e.Property { if errStr := loadStructField(sv, p); errStr != "" { fieldName, reason = proto.GetString(p.Name), errStr } } for _, p := range e.RawProperty { if errStr := loadStructField(sv, p); errStr != "" { fieldName, reason = proto.GetString(p.Name), errStr } } if reason != "" { return &ErrFieldMismatch{ Key: k, StructType: sv.Type(), FieldName: fieldName, Reason: reason, } } return nil }
func (c *conn) getdir(t *T, tx txn) { path := pb.GetString(t.Path) if g := c.getterFor(t); g != nil { go func() { ents, rev := g.Get(path) if rev == store.Missing { c.respond(t, Valid|Done, nil, noEnt) return } if rev != store.Dir { c.respond(t, Valid|Done, nil, notDir) return } offset := int(pb.GetInt32(t.Offset)) limit := int(pb.GetInt32(t.Limit)) if limit <= 0 { limit = len(ents) } if offset < 0 { offset = 0 } end := offset + limit if end > len(ents) { end = len(ents) } for _, e := range ents[offset:end] { select { case <-tx.cancel: c.closeTxn(*t.Tag) return default: } c.respond(t, Valid, tx.cancel, &R{Path: &e}) } c.respond(t, Done, nil, &R{}) }() } }
func (c *conn) get(t *T, tx txn) { if g := c.getterFor(t); g != nil { v, rev := g.Get(pb.GetString(t.Path)) if rev == store.Dir { c.respond(t, Valid|Done, nil, isDir) return } var r R r.Rev = &rev if len(v) == 1 { // not missing r.Value = []byte(v[0]) } c.respond(t, Valid|Done, nil, &r) } }
func (c *conn) walk(t *T, tx txn) { pat := pb.GetString(t.Path) glob, err := store.CompileGlob(pat) if err != nil { c.respond(t, Valid|Done, nil, errResponse(err)) return } offset := pb.GetInt32(t.Offset) var limit int32 = math.MaxInt32 if t.Limit != nil { limit = pb.GetInt32(t.Limit) } if g := c.getterFor(t); g != nil { go func() { f := func(path, body string, rev int64) (stop bool) { select { case <-tx.cancel: c.closeTxn(*t.Tag) return true default: } if offset <= 0 && limit > 0 { var r R r.Path = &path r.Value = []byte(body) r.Rev = &rev c.respond(t, Valid|Set, tx.cancel, &r) limit-- } offset-- return false } stopped := store.Walk(g, glob, f) if !stopped { c.respond(t, Done, nil, &R{}) } }() } }
func (c *conn) wait(t *T, tx txn) { pat := pb.GetString(t.Path) glob, err := store.CompileGlob(pat) if err != nil { c.respond(t, Valid|Done, nil, errResponse(err)) return } var w *store.Watch rev := pb.GetInt64(t.Rev) if rev == 0 { w, err = store.NewWatch(c.s.St, glob), nil } else { w, err = store.NewWatchFrom(c.s.St, glob, rev) } switch err { case nil: // nothing case store.ErrTooLate: c.respond(t, Valid|Done, nil, tooLate) default: c.respond(t, Valid|Done, nil, errResponse(err)) } go func() { defer w.Stop() ev := <-w.C r := R{ Path: &ev.Path, Value: []byte(ev.Body), Rev: &ev.Seqn, } var flag int32 switch { case ev.IsSet(): flag = Set case ev.IsDel(): flag = Del } c.respond(t, Valid|flag, nil, &r) }() }
func (t *txn) stat() { if t.c.access == false { t.respondOsError(os.EACCES) return } go func() { g, err := t.getter() if err != nil { t.respondOsError(err) return } len, rev := g.Stat(proto.GetString(t.req.Path)) t.resp.Len = &len t.resp.Rev = &rev t.respond() }() }
// Receives messages from remote client and acts upon them if appropriate. func (cl *client) RecvLoop(cs chan<- Msg) { defer logAndClose(cl.conn) for { msg, err := readMessage(cl.conn) if err != nil { // Remove client if something went wrong cs <- removeClientMsg{cl, "Reading message from client failed: " + err.String()} return } switch *msg.Type { case protocol.Message_Type(protocol.Message_DISCONNECT): cs <- removeClientMsg{cl, proto.GetString(msg.Disconnect.ReasonStr)} return default: // TODO: If no proper avatar has been started, this will block, fix? // We could check cl.avatar for nil cl.RecvQueue <- msg // Forward to avatar } } }
func main() { flag.Usage = usage flag.Parse() if *helpShort || *helpLong || flag.NArg() == 0 { flag.Usage() os.Exit(1) } fds, err := parser.ParseFiles(flag.Args(), strings.Split(*importPath, ",", -1)) if err != nil { log.Exitf("Failed parsing: %v", err) } resolver.ResolveSymbols(fds) fmt.Println("-----") proto.MarshalText(os.Stdout, fds) fmt.Println("-----") // Find plugin. pluginPath := fullPath(*pluginBinary, strings.Split(os.Getenv("PATH"), ":", -1)) if pluginPath == "" { log.Exitf("Failed finding plugin binary %q", *pluginBinary) } // Start plugin subprocess. pluginIn, meOut, err := os.Pipe() if err != nil { log.Exitf("Failed creating pipe: %v", err) } meIn, pluginOut, err := os.Pipe() if err != nil { log.Exitf("Failed creating pipe: %v", err) } pid, err := os.ForkExec(pluginPath, nil, nil, "/", []*os.File{pluginIn, pluginOut, os.Stderr}) if err != nil { log.Exitf("Failed forking plugin: %v", err) } pluginIn.Close() pluginOut.Close() // Send request. cgRequest := &plugin.CodeGeneratorRequest{ FileToGenerate: flag.Args(), // TODO: proto_file should be topologically sorted (bottom-up) ProtoFile: fds.File, } buf, err := proto.Marshal(cgRequest) if err != nil { log.Exitf("Failed marshaling CG request: %v", err) } _, err = meOut.Write(buf) if err != nil { log.Exitf("Failed writing CG request: %v", err) } meOut.Close() w, err := os.Wait(pid, 0) if err != nil { log.Exitf("Failed waiting for plugin: %v", err) } if w.ExitStatus() != 0 { log.Exitf("Plugin exited with status %d", w.ExitStatus()) } // Read response. cgResponse := new(plugin.CodeGeneratorResponse) if buf, err = ioutil.ReadAll(meIn); err != nil { log.Exitf("Failed reading CG response: %v", err) } if err = proto.Unmarshal(buf, cgResponse); err != nil { log.Exitf("Failed unmarshaling CG response: %v", err) } // TODO: check cgResponse.Error // TODO: write files for _, f := range cgResponse.File { fmt.Printf("--[ %v ]--\n", proto.GetString(f.Name)) fmt.Println(proto.GetString(f.Content)) } fmt.Println("-----") }
func newError(t *txn) *Error { return &Error{ Err: *t.resp.ErrCode, Detail: proto.GetString(t.resp.ErrDetail), } }
// loadStructField converts a Property into a field of an existing struct, // or into an element of a slice-typed struct field. // It returns an error message, or "" for success. func loadStructField(sv reflect.Value, p *pb.Property) string { fieldName := proto.GetString(p.Name) v := sv.FieldByName(fieldName) if !v.IsValid() { return "no such struct field" } if unexported(fieldName) { return "unexported struct field" } var slice reflect.Value if proto.GetBool(p.Multiple) { if v.Kind() != reflect.Slice { return "multiple-valued property requires a slice field type" } if v.Len() > maxSliceFieldLen-1 { return "slice is too long" } slice = v v = reflect.New(v.Type().Elem()).Elem() } switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if p.Value.Int64Value == nil { return typeMismatchReason(p, v) } x := *p.Value.Int64Value if v.OverflowInt(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetInt(x) case reflect.Bool: if p.Value.BooleanValue == nil { return typeMismatchReason(p, v) } v.SetBool(*p.Value.BooleanValue) case reflect.String: if p.Value.StringValue == nil { return typeMismatchReason(p, v) } v.SetString(*p.Value.StringValue) case reflect.Float32, reflect.Float64: if p.Value.DoubleValue == nil { return typeMismatchReason(p, v) } x := *p.Value.DoubleValue if v.OverflowFloat(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetFloat(x) case reflect.Ptr: if _, ok := v.Interface().(*Key); !ok { return typeMismatchReason(p, v) } if p.Value.Referencevalue == nil { return typeMismatchReason(p, v) } k, err := referenceValueToKey(p.Value.Referencevalue) if err != nil { return "stored key was invalid" } v.Set(reflect.ValueOf(k)) case reflect.Slice: if _, ok := v.Interface().([]byte); !ok { return typeMismatchReason(p, v) } if p.Value.StringValue == nil { return typeMismatchReason(p, v) } b := []byte(*p.Value.StringValue) v.Set(reflect.ValueOf(b)) default: return typeMismatchReason(p, v) } if slice.IsValid() { slice.Set(reflect.Append(slice, v)) } return "" }
func (c *conn) stat(t *T, tx txn) { if g := c.getterFor(t); g != nil { ln, rev := g.Stat(pb.GetString(t.Path)) c.respond(t, Valid|Done, nil, &R{Len: &ln, Rev: &rev}) } }