func (s *S) TestUnmarshalAllItemsWithPtrSetter(c *C) { for _, item := range allItems { for i := 0; i != 2; i++ { var field *setterType if i == 0 { obj := &ptrSetterDoc{} err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj) c.Assert(err, IsNil) field = obj.Field } else { obj := &valSetterDoc{} err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj) c.Assert(err, IsNil) field = &obj.Field } if item.data == "" { // Nothing to unmarshal. Should be untouched. if i == 0 { c.Assert(field, IsNil) } else { c.Assert(field.received, IsNil) } } else { expected := item.obj.(bson.M)["_"] c.Assert(field, NotNil, Commentf("Pointer not initialized (%#v)", expected)) c.Assert(field.received, DeepEquals, expected) } } } }
func (s *S) TestUnmarshalMapDocumentTooShort(c *C) { for _, data := range corruptedData { err := bson.Unmarshal([]byte(data), bson.M{}) c.Assert(err, ErrorMatches, "Document is corrupted") err = bson.Unmarshal([]byte(data), &struct{}{}) c.Assert(err, ErrorMatches, "Document is corrupted") } }
func (d *Decoder) Decode(pv interface{}) (err error) { var lbuf [4]byte n, err := d.r.Read(lbuf[:]) if n == 0 { err = io.EOF return } if n != 4 { err = errors.New(fmt.Sprintf("Corrupted BSON stream: could only read %d", n)) return } if err != nil { return } length := (int(lbuf[0]) << 0) | (int(lbuf[1]) << 8) | (int(lbuf[2]) << 16) | (int(lbuf[3]) << 24) buf := make([]byte, length) copy(buf[0:4], lbuf[:]) _, err = d.r.Read(buf[4:]) if err != nil { return } err = bson.Unmarshal(buf, pv) return }
func (s *S) TestUnmarshalZeroesMap(c *C) { data, err := bson.Marshal(bson.M{"b": 2}) c.Assert(err, IsNil) m := bson.M{"a": 1} err = bson.Unmarshal(data, &m) c.Assert(err, IsNil) c.Assert(m, DeepEquals, bson.M{"b": 2}) }
func (s *S) TestUnmarshalNilInStruct(c *C) { // Nil is the default value, so we need to ensure it's indeed being set. b := byte(1) v := &struct{ Ptr *byte }{&b} err := bson.Unmarshal([]byte(wrapInDoc("\x0Aptr\x00")), v) c.Assert(err, IsNil) c.Assert(v, DeepEquals, &struct{ Ptr *byte }{nil}) }
func (s *S) TestUnmarshalSampleItems(c *C) { for i, item := range sampleItems { value := bson.M{} err := bson.Unmarshal([]byte(item.data), value) c.Assert(err, IsNil) c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d", i)) } }
func (s *S) TestMarshalShortWithGetter(c *C) { obj := typeWithIntGetter{42} data, err := bson.Marshal(obj) c.Assert(err, IsNil) m := bson.M{} err = bson.Unmarshal(data, m) c.Assert(m["v"], Equals, 42) }
// GetMeta unmarshals the optional "metadata" field associated with the // file into the result parameter. The meaning of keys under that field // is user-defined. For example: // // result := struct{ INode int }{} // err = file.GetMeta(&result) // if err != nil { // panic(err.String()) // } // fmt.Printf("inode: %d\n", result.INode) // func (file *GridFile) GetMeta(result interface{}) (err error) { file.m.Lock() if file.doc.Metadata != nil { err = bson.Unmarshal(file.doc.Metadata.Data, result) } file.m.Unlock() return }
func (s *S) TestUnmarshalAllItems(c *C) { for i, item := range allItems { value := bson.M{} err := bson.Unmarshal([]byte(wrapInDoc(item.data)), value) c.Assert(err, IsNil) c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item)) } }
func (s *S) TestUnmarshalZeroesStruct(c *C) { data, err := bson.Marshal(bson.M{"b": 2}) c.Assert(err, IsNil) type T struct{ A, B int } v := T{A: 1} err = bson.Unmarshal(data, &v) c.Assert(err, IsNil) c.Assert(v.A, Equals, 0) c.Assert(v.B, Equals, 2) }
func (s *S) TestUnmarshalNonNilInterface(c *C) { data, err := bson.Marshal(bson.M{"b": 2}) c.Assert(err, IsNil) m := bson.M{"a": 1} var i interface{} i = m err = bson.Unmarshal(data, &i) c.Assert(err, IsNil) c.Assert(i, DeepEquals, bson.M{"b": 2}) c.Assert(m, DeepEquals, bson.M{"a": 1}) }
func objToDoc(obj interface{}) (d bson.D, err error) { data, err := bson.Marshal(obj) if err != nil { return nil, err } err = bson.Unmarshal(data, &d) if err != nil { return nil, err } return d, err }
func testCrossPair(c *C, dump interface{}, load interface{}) { c.Logf("Dump: %#v", dump) c.Logf("Load: %#v", load) zero := makeZeroDoc(load) data, err := bson.Marshal(dump) c.Assert(err, IsNil) c.Logf("Dumped: %#v", string(data)) err = bson.Unmarshal(data, zero) c.Assert(err, IsNil) c.Logf("Loaded: %#v", zero) c.Assert(zero, DeepEquals, load) }
func BenchmarkUnmarhsalStruct(b *testing.B) { v := BenchT{A: "A", D: "D", E: "E"} data, err := bson.Marshal(&v) if err != nil { panic(err) } b.ResetTimer() for i := 0; i < b.N; i++ { err = bson.Unmarshal(data, &v) } if err != nil { panic(err) } }
func BenchmarkUnmarhsalMap(b *testing.B) { m := bson.M{"a": "a", "d": "d", "e": "e"} data, err := bson.Marshal(&m) if err != nil { panic(err) } b.ResetTimer() for i := 0; i < b.N; i++ { err = bson.Unmarshal(data, &m) } if err != nil { panic(err) } }
func (s *S) TestUnmarshalSetterSetZero(c *C) { setterResult["foo"] = bson.SetZero defer delete(setterResult, "field") data, err := bson.Marshal(bson.M{"field": "foo"}) c.Assert(err, IsNil) m := map[string]*setterType{} err = bson.Unmarshal([]byte(data), m) c.Assert(err, IsNil) value, ok := m["field"] c.Assert(ok, Equals, true) c.Assert(value, IsNil) }
func (s *S) TestUnmarshalErrorItems(c *C) { for _, item := range unmarshalErrorItems { data := []byte(wrapInDoc(item.data)) var value interface{} switch reflect.ValueOf(item.obj).Kind() { case reflect.Map, reflect.Ptr: value = makeZeroDoc(item.obj) case reflect.Invalid: value = bson.M{} default: value = item.obj } err := bson.Unmarshal(data, value) c.Assert(err, ErrorMatches, item.error) } }
func TestServiceRPCBasic(t *testing.T) { var addr net.Addr config := &skynet.ServiceConfig{} service := CreateService(EchoRPC{}, config) service.ClientInfo = make(map[string]ClientInfo, 1) addr = &net.TCPAddr{ IP: net.ParseIP("127.0.0.1"), Port: 123, } service.ClientInfo["123"] = ClientInfo{ Address: addr, } srpc := NewServiceRPC(service) in := M{"Hi": "there"} out := &M{} sin := skynet.ServiceRPCIn{ RequestInfo: &skynet.RequestInfo{ RequestID: "id", OriginAddress: addr.String(), ConnectionAddress: addr.String(), }, Method: "Foo", ClientID: "123", } sin.In, _ = bson.Marshal(in) sout := skynet.ServiceRPCOut{} err := srpc.Forward(sin, &sout) if err != nil { t.Error(err) } bson.Unmarshal(sout.Out, out) if v, ok := (*out)["Hi"].(string); !ok || v != "there" { t.Error(fmt.Sprintf("Expected %v, got %v", in, *out)) } }
func (s *S) TestUnmarshalSetterErrors(c *C) { boom := errors.New("BOOM") setterResult["2"] = boom defer delete(setterResult, "2") m := map[string]*setterType{} data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" + "\x02def\x00\x02\x00\x00\x002\x00" + "\x02ghi\x00\x02\x00\x00\x003\x00") err := bson.Unmarshal([]byte(data), m) c.Assert(err, Equals, boom) c.Assert(m["abc"], NotNil) c.Assert(m["def"], IsNil) c.Assert(m["ghi"], IsNil) c.Assert(m["abc"].received, Equals, "1") }
func (socket *mongoSocket) resetNonce() { debugf("Socket %p to %s: requesting a new nonce", socket, socket.addr) op := &queryOp{} op.query = &getNonceCmd{GetNonce: 1} op.collection = "admin.$cmd" op.limit = -1 op.replyFunc = func(err error, reply *replyOp, docNum int, docData []byte) { if err != nil { socket.kill(errors.New("getNonce: "+err.Error()), true) return } result := &getNonceResult{} err = bson.Unmarshal(docData, &result) if err != nil { socket.kill(errors.New("Failed to unmarshal nonce: "+err.Error()), true) return } debugf("Socket %p to %s: nonce unmarshalled: %#v", socket, socket.addr, result) if result.Code == 13390 { // mongos doesn't yet support auth (see http://j.mp/mongos-auth) result.Nonce = "mongos" } else if result.Nonce == "" { var msg string if result.Err != "" { msg = fmt.Sprintf("Got an empty nonce: %s (%d)", result.Err, result.Code) } else { msg = "Got an empty nonce" } socket.kill(errors.New(msg), true) return } socket.Lock() if socket.cachedNonce != "" { socket.Unlock() panic("resetNonce: nonce already cached") } socket.cachedNonce = result.Nonce socket.gotNonce.Signal() socket.Unlock() } err := socket.Query(op) if err != nil { socket.kill(errors.New("resetNonce: "+err.Error()), true) } }
func (s *S) TestUnmarshalSetterOmits(c *C) { setterResult["2"] = &bson.TypeError{} setterResult["4"] = &bson.TypeError{} defer func() { delete(setterResult, "2") delete(setterResult, "4") }() m := map[string]*setterType{} data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" + "\x02def\x00\x02\x00\x00\x002\x00" + "\x02ghi\x00\x02\x00\x00\x003\x00" + "\x02jkl\x00\x02\x00\x00\x004\x00") err := bson.Unmarshal([]byte(data), m) c.Assert(err, IsNil) c.Assert(m["abc"], NotNil) c.Assert(m["def"], IsNil) c.Assert(m["ghi"], NotNil) c.Assert(m["jkl"], IsNil) c.Assert(m["abc"].received, Equals, "1") c.Assert(m["ghi"].received, Equals, "3") }
// ServiceRPC.Forward is the entry point for RPC calls. It wraps actual RPC calls // and provides a slot for the RequestInfo. The parameters to the actual RPC // calls are transmitted in a []byte, and are then marshalled/unmarshalled on // either end. func (srpc *ServiceRPC) Forward(in skynet.ServiceRPCIn, out *skynet.ServiceRPCOut) (err error) { srpc.service.activeRequests.Add(1) defer srpc.service.activeRequests.Done() srpc.service.Delegate.MethodCalled(in.Method) clientInfo, ok := srpc.service.getClientInfo(in.ClientID) if !ok { err = errors.New("did not provide the ClientID") return } in.RequestInfo.ConnectionAddress = clientInfo.Address.String() if in.RequestInfo.OriginAddress == "" || !srpc.service.IsTrusted(clientInfo.Address) { in.RequestInfo.OriginAddress = in.RequestInfo.ConnectionAddress } mc := MethodCall{ MethodName: in.Method, RequestInfo: in.RequestInfo, } if srpc.service.Log != nil { srpc.service.Log.Trace(fmt.Sprintf("%+v", mc)) } m, ok := srpc.methods[in.Method] if !ok { err = errors.New(fmt.Sprintf("No such method %q", in.Method)) return } inValuePtr := reflect.New(m.Type().In(2)) err = bson.Unmarshal(in.In, inValuePtr.Interface()) if err != nil { return } // Allocate the out parameter of the RPC call. outType := m.Type().In(3) var outValue reflect.Value switch outType.Kind() { case reflect.Ptr: outValue = reflect.New(m.Type().In(3).Elem()) case reflect.Map: outValue = reflect.MakeMap(outType) default: panic("illegal out param type") } srpc.service.Stats.LastRequest = time.Now().Format("2006-01-02T15:04:05Z-0700") startTime := time.Now().UnixNano() params := []reflect.Value{ reflect.ValueOf(srpc.service.Delegate), reflect.ValueOf(in.RequestInfo), inValuePtr.Elem(), outValue, } returns := m.Call(params) duration := time.Now().UnixNano() - startTime // Update stats atomic.AddInt64(&srpc.service.Stats.RequestsServed, 1) atomic.AddInt64((*int64)(&srpc.service.Stats.TotalDuration), int64(duration)) // ns srpc.service.Stats.AverageResponseTime = srpc.service.Stats.TotalDuration / time.Duration(srpc.service.Stats.RequestsServed) mcp := MethodCompletion{ MethodName: in.Method, RequestInfo: in.RequestInfo, Duration: duration, } if srpc.service.Log != nil { srpc.service.Log.Trace(fmt.Sprintf("%+v", mcp)) } out.Out, err = bson.Marshal(outValue.Interface()) if err != nil { return } erri := returns[0].Interface() var rerr error if erri != nil { rerr, _ := erri.(error) out.ErrString = rerr.Error() } srpc.service.Delegate.MethodCompleted(in.Method, duration, rerr) return }
func (c *ServiceClient) send(retry, giveup time.Duration, ri *skynet.RequestInfo, fn string, in interface{}, out interface{}) (err error) { if ri == nil { ri = &skynet.RequestInfo{ RequestID: skynet.UUID(), } } attempts := make(chan sendAttempt) var ticker <-chan time.Time if retry > 0 { ticker = time.NewTicker(retry).C } var timeout <-chan time.Time if giveup > 0 { timeout = time.NewTimer(giveup).C } doneSignal := make(chan bool) attemptCount := 1 defer func() { go func() { for i := 0; i < attemptCount; i++ { doneSignal <- true } }() }() go c.attemptSend(doneSignal, attempts, ri, fn, in) for { select { case <-ticker: attemptCount++ ri.RetryCount++ go c.attemptSend(doneSignal, attempts, ri, fn, in) case <-timeout: if err == nil { err = ErrRequestTimeout } // otherwise use the last error reported from an attempt return case attempt := <-attempts: err = attempt.err if err != nil { if _, ok := err.(serviceError); !ok { // error during transmition, abort this attempt if giveup == 0 { return } continue } } unmarshallerr := bson.Unmarshal(attempt.result, out) if unmarshallerr != nil { err = unmarshallerr } return } } return }
func testUnmarshal(c *C, data string, obj interface{}) { zero := makeZeroDoc(obj) err := bson.Unmarshal([]byte(data), zero) c.Assert(err, IsNil) c.Assert(zero, DeepEquals, obj) }
func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) { obj := &setterType{} err := bson.Unmarshal([]byte(sampleItems[0].data), obj) c.Assert(err, IsNil) c.Assert(obj.received, DeepEquals, bson.M{"hello": "world"}) }
func (socket *mongoSocket) Login(db string, user string, pass string) error { socket.Lock() for _, a := range socket.auth { if a.db == db && a.user == user && a.pass == pass { debugf("Socket %p to %s: login: db=%q user=%q (already logged in)", socket, socket.addr, db, user) socket.Unlock() return nil } } if auth, found := socket.dropLogout(db, user, pass); found { debugf("Socket %p to %s: login: db=%q user=%q (cached)", socket, socket.addr, db, user) socket.auth = append(socket.auth, auth) socket.Unlock() return nil } socket.Unlock() debugf("Socket %p to %s: login: db=%q user=%q", socket, socket.addr, db, user) // Note that this only works properly because this function is // synchronous, which means the nonce won't get reset while we're // using it and any other login requests will block waiting for a // new nonce provided in the defer call below. nonce, err := socket.getNonce() if err != nil { return err } defer socket.resetNonce() psum := md5.New() psum.Write([]byte(user + ":mongo:" + pass)) ksum := md5.New() ksum.Write([]byte(nonce + user)) ksum.Write([]byte(hex.EncodeToString(psum.Sum(nil)))) key := hex.EncodeToString(ksum.Sum(nil)) cmd := authCmd{Authenticate: 1, User: user, Nonce: nonce, Key: key} var mutex sync.Mutex var replyErr error mutex.Lock() op := queryOp{} op.query = &cmd op.collection = db + ".$cmd" op.limit = -1 op.replyFunc = func(err error, reply *replyOp, docNum int, docData []byte) { defer mutex.Unlock() if err != nil { replyErr = err return } // Must handle this within the read loop for the socket, so // that concurrent login requests are properly ordered. result := &authResult{} err = bson.Unmarshal(docData, result) if err != nil { replyErr = err return } if !result.Ok { replyErr = errors.New(result.ErrMsg) } socket.Lock() socket.dropAuth(db) socket.auth = append(socket.auth, authInfo{db, user, pass}) socket.Unlock() } err = socket.Query(&op) if err != nil { return err } mutex.Lock() // Wait. if replyErr != nil { debugf("Socket %p to %s: login error: %s", socket, socket.addr, replyErr) } else { debugf("Socket %p to %s: login successful", socket, socket.addr) } return replyErr }
// Estimated minimum cost per socket: 1 goroutine + memory for the largest // document ever seen. func (socket *mongoSocket) readLoop() { p := make([]byte, 36) // 16 from header + 20 from OP_REPLY fixed fields s := make([]byte, 4) conn := socket.conn // No locking, conn never changes. for { // XXX Handle timeouts, , etc err := fill(conn, p) if err != nil { socket.kill(err, true) return } totalLen := getInt32(p, 0) responseTo := getInt32(p, 8) opCode := getInt32(p, 12) // Don't use socket.server.Addr here. socket is not // locked and socket.server may go away. debugf("Socket %p to %s: got reply (%d bytes)", socket, socket.addr, totalLen) _ = totalLen if opCode != 1 { socket.kill(errors.New("opcode != 1, corrupted data?"), true) return } reply := replyOp{ flags: uint32(getInt32(p, 16)), cursorId: getInt64(p, 20), firstDoc: getInt32(p, 28), replyDocs: getInt32(p, 32), } stats.receivedOps(+1) stats.receivedDocs(int(reply.replyDocs)) socket.Lock() replyFunc, replyFuncFound := socket.replyFuncs[uint32(responseTo)] socket.Unlock() if replyFunc != nil && reply.replyDocs == 0 { replyFunc(nil, &reply, -1, nil) } else { for i := 0; i != int(reply.replyDocs); i++ { err := fill(conn, s) if err != nil { socket.kill(err, true) return } b := make([]byte, int(getInt32(s, 0))) // copy(b, s) in an efficient way. b[0] = s[0] b[1] = s[1] b[2] = s[2] b[3] = s[3] err = fill(conn, b[4:]) if err != nil { socket.kill(err, true) return } if globalDebug && globalLogger != nil { m := bson.M{} if err := bson.Unmarshal(b, m); err == nil { debugf("Socket %p to %s: received document: %#v", socket, socket.addr, m) } } if replyFunc != nil { replyFunc(nil, &reply, i, b) } // XXX Do bound checking against totalLen. } } // Only remove replyFunc after iteration, so that kill() will see it. socket.Lock() if replyFuncFound { delete(socket.replyFuncs, uint32(responseTo)) } socket.Unlock() // XXX Do bound checking against totalLen. } }