Skip to content

Commit

Permalink
Merge v2-unstable into v2.
Browse files Browse the repository at this point in the history
  • Loading branch information
niemeyer committed May 29, 2015
2 parents c6a7dce + e1e5be4 commit 7c85a0d
Show file tree
Hide file tree
Showing 27 changed files with 942 additions and 119 deletions.
2 changes: 1 addition & 1 deletion auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ func (s *S) TestAuthLoginCachingWithNewSession(c *C) {

coll := session.DB("mydb").C("mycoll")
err = coll.Insert(M{"n": 1})
c.Assert(err, ErrorMatches, "unauthorized|need to login|not authorized for .*")
c.Assert(err, ErrorMatches, "unauthorized|need to login|not authorized .*")
}

func (s *S) TestAuthLoginCachingAcrossPool(c *C) {
Expand Down
23 changes: 23 additions & 0 deletions bson/bson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,25 @@ func (i *getterSetterInt) SetBSON(raw bson.Raw) error {
return err
}

type ifaceType interface {
Hello()
}

type ifaceSlice []ifaceType

func (s *ifaceSlice) SetBSON(raw bson.Raw) error {
var ns []int
if err := raw.Unmarshal(&ns); err != nil {
return err
}
*s = make(ifaceSlice, ns[0])
return nil
}

func (s ifaceSlice) GetBSON() (interface{}, error) {
return []int{len(s)}, nil
}

type (
MyString string
MyBytes []byte
Expand Down Expand Up @@ -1249,6 +1268,7 @@ var twoWayCrossItems = []crossTypeItem{

// arrays
{&struct{ V [2]int }{[...]int{1, 2}}, map[string][2]int{"v": [2]int{1, 2}}},
{&struct{ V [2]byte }{[...]byte{1, 2}}, map[string][2]byte{"v": [2]byte{1, 2}}},

// zero time
{&struct{ V time.Time }{}, map[string]interface{}{"v": time.Time{}}},
Expand Down Expand Up @@ -1281,6 +1301,9 @@ var twoWayCrossItems = []crossTypeItem{
// bson.D <=> non-struct getter/setter
{&bson.D{{"a", 1}}, &getterSetterD{{"a", 1}, {"suffix", true}}},
{&bson.D{{"a", 42}}, &gsintvar},

// Interface slice setter.
{&struct{ V ifaceSlice }{ifaceSlice{nil, nil, nil}}, bson.M{"v": []interface{}{3}}},
}

// Same thing, but only one way (obj1 => obj2).
Expand Down
19 changes: 12 additions & 7 deletions bson/decode.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// BSON library for Go
//
//
// Copyright (c) 2010-2012 - Gustavo Niemeyer <[email protected]>
//
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Expand Down Expand Up @@ -474,6 +474,11 @@ func (d *decoder) readElemTo(out reflect.Value, kind byte) (good bool) {
panic("Can't happen. Handled above.")
case 0x04: // Array
outt := out.Type()
if setterStyle(outt) != setterNone {
// Skip the value so its data is handed to the setter below.
d.dropElem(kind)
break
}
for outt.Kind() == reflect.Ptr {
outt = outt.Elem()
}
Expand Down
30 changes: 20 additions & 10 deletions bson/encode.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// BSON library for Go
//
//
// Copyright (c) 2010-2012 - Gustavo Niemeyer <[email protected]>
//
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Expand Down Expand Up @@ -212,7 +212,7 @@ func (e *encoder) addSlice(v reflect.Value) {
return
}
l := v.Len()
et := v.Type().Elem()
et := v.Type().Elem()
if et == typeDocElem {
for i := 0; i < l; i++ {
elem := v.Index(i).Interface().(DocElem)
Expand Down Expand Up @@ -365,7 +365,17 @@ func (e *encoder) addElem(name string, v reflect.Value, minSize bool) {
et := v.Type().Elem()
if et.Kind() == reflect.Uint8 {
e.addElemName('\x05', name)
e.addBinary('\x00', v.Slice(0, v.Len()).Interface().([]byte))
if v.CanAddr() {
e.addBinary('\x00', v.Slice(0, v.Len()).Interface().([]byte))
} else {
n := v.Len()
e.addInt32(int32(n))
e.addBytes('\x00')
for i := 0; i < n; i++ {
el := v.Index(i)
e.addBytes(byte(el.Uint()))
}
}
} else {
e.addElemName('\x04', name)
e.addDoc(v)
Expand Down Expand Up @@ -415,7 +425,7 @@ func (e *encoder) addElem(name string, v reflect.Value, minSize bool) {
case time.Time:
// MongoDB handles timestamps as milliseconds.
e.addElemName('\x09', name)
e.addInt64(s.Unix() * 1000 + int64(s.Nanosecond() / 1e6))
e.addInt64(s.Unix()*1000 + int64(s.Nanosecond()/1e6))

case url.URL:
e.addElemName('\x02', name)
Expand Down
40 changes: 39 additions & 1 deletion bulk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (s *S) TestBulkInsertError(c *C) {

coll := session.DB("mydb").C("mycoll")
bulk := coll.Bulk()
bulk.Insert(M{"_id": 1}, M{"_id": 2}, M{"_id": 2}, M{"n": 3})
bulk.Insert(M{"_id": 1}, M{"_id": 2}, M{"_id": 2}, M{"_id": 3})
_, err = bulk.Run()
c.Assert(err, ErrorMatches, ".*duplicate key.*")

Expand Down Expand Up @@ -91,3 +91,41 @@ func (s *S) TestBulkInsertErrorUnordered(c *C) {
c.Assert(err, IsNil)
c.Assert(res, DeepEquals, []doc{{1}, {2}, {3}})
}

func (s *S) TestBulkInsertErrorUnorderedSplitBatch(c *C) {
// The server has a batch limit of 1000 documents when using write commands.
// This artificial limit did not exist with the old wire protocol, so to
// avoid compatibility issues the implementation internally split batches
// into the proper size and delivers them one by one. This test ensures that
// the behavior of unordered (that is, continue on error) remains correct
// when errors happen and there are batches left.
session, err := mgo.Dial("localhost:40001")
c.Assert(err, IsNil)
defer session.Close()

coll := session.DB("mydb").C("mycoll")
bulk := coll.Bulk()
bulk.Unordered()

const total = 4096
type doc struct {
Id int `_id`
}
docs := make([]interface{}, total)
for i := 0; i < total; i++ {
docs[i] = doc{i}
}
docs[1] = doc{0}
bulk.Insert(docs...)
_, err = bulk.Run()
c.Assert(err, ErrorMatches, ".*duplicate key.*")

n, err := coll.Count()
c.Assert(err, IsNil)
c.Assert(n, Equals, total-1)

var res doc
err = coll.FindId(1500).One(&res)
c.Assert(err, IsNil)
c.Assert(res.Id, Equals, 1500)
}
11 changes: 6 additions & 5 deletions cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,18 @@ func (cluster *mongoCluster) syncServer(server *mongoServer) (info *mongoServerI

if result.IsMaster {
debugf("SYNC %s is a master.", addr)
// Made an incorrect assumption above, so fix stats.
stats.conn(-1, false)
stats.conn(+1, true)
if !server.info.Master {
// Made an incorrect assumption above, so fix stats.
stats.conn(-1, false)
stats.conn(+1, true)
}
} else if result.Secondary {
debugf("SYNC %s is a slave.", addr)
} else if cluster.direct {
logf("SYNC %s in unknown state. Pretending it's a slave due to direct connection.", addr)
} else {
logf("SYNC %s is neither a master nor a slave.", addr)
// Made an incorrect assumption above, so fix stats.
stats.conn(-1, false)
// Let stats track it as whatever was known before.
return nil, nil, errors.New(addr + " is not a master nor slave")
}

Expand Down
2 changes: 0 additions & 2 deletions cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1185,8 +1185,6 @@ func (s *S) TestRemovalOfClusterMember(c *C) {
c.Logf("========== Removing slave: %s ==========", slaveAddr)

master.Run(bson.D{{"$eval", `rs.remove("` + slaveAddr + `")`}}, nil)
err = master.Ping()
c.Assert(err, Equals, io.EOF)

master.Refresh()

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion saslimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
package mgo

import (
"gopkg.in/mgo.v2/sasl"
"gopkg.in/mgo.v2/internal/sasl"
)

func saslNew(cred Credential, host string) (saslStepper, error) {
Expand Down
Loading

0 comments on commit 7c85a0d

Please sign in to comment.