blob: 4f68c3c2cf1c66f786d108cd5850637b5af23cd7 [file] [log] [blame]
Don Newton379ae252019-04-01 12:17:06 -04001// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7package command
8
9import (
10 "context"
11
12 "fmt"
13
14 "github.com/mongodb/mongo-go-driver/bson"
15 "github.com/mongodb/mongo-go-driver/mongo/readpref"
16 "github.com/mongodb/mongo-go-driver/x/bsonx"
17 "github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
18 "github.com/mongodb/mongo-go-driver/x/network/description"
19 "github.com/mongodb/mongo-go-driver/x/network/result"
20 "github.com/mongodb/mongo-go-driver/x/network/wiremessage"
21)
22
23// GetLastError represents the getLastError command.
24//
25// The getLastError command is used for getting the last
26// error from the last command on a connection.
27//
28// Since GetLastError only makes sense in the context of
29// a single connection, there is no Dispatch method.
30type GetLastError struct {
31 Clock *session.ClusterClock
32 Session *session.Client
33
34 err error
35 res result.GetLastError
36}
37
38// Encode will encode this command into a wire message for the given server description.
39func (gle *GetLastError) Encode() (wiremessage.WireMessage, error) {
40 encoded, err := gle.encode()
41 if err != nil {
42 return nil, err
43 }
44 return encoded.Encode(description.SelectedServer{})
45}
46
47func (gle *GetLastError) encode() (*Read, error) {
48 // This can probably just be a global variable that we reuse.
49 cmd := bsonx.Doc{{"getLastError", bsonx.Int32(1)}}
50
51 return &Read{
52 Clock: gle.Clock,
53 DB: "admin",
54 ReadPref: readpref.Secondary(),
55 Session: gle.Session,
56 Command: cmd,
57 }, nil
58}
59
60// Decode will decode the wire message using the provided server description. Errors during decoding
61// are deferred until either the Result or Err methods are called.
62func (gle *GetLastError) Decode(wm wiremessage.WireMessage) *GetLastError {
63 reply, ok := wm.(wiremessage.Reply)
64 if !ok {
65 gle.err = fmt.Errorf("unsupported response wiremessage type %T", wm)
66 return gle
67 }
68 rdr, err := decodeCommandOpReply(reply)
69 if err != nil {
70 gle.err = err
71 return gle
72 }
73 return gle.decode(rdr)
74}
75
76func (gle *GetLastError) decode(rdr bson.Raw) *GetLastError {
77 err := bson.Unmarshal(rdr, &gle.res)
78 if err != nil {
79 gle.err = err
80 return gle
81 }
82
83 return gle
84}
85
86// Result returns the result of a decoded wire message and server description.
87func (gle *GetLastError) Result() (result.GetLastError, error) {
88 if gle.err != nil {
89 return result.GetLastError{}, gle.err
90 }
91
92 return gle.res, nil
93}
94
95// Err returns the error set on this command.
96func (gle *GetLastError) Err() error { return gle.err }
97
98// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
99func (gle *GetLastError) RoundTrip(ctx context.Context, rw wiremessage.ReadWriter) (result.GetLastError, error) {
100 cmd, err := gle.encode()
101 if err != nil {
102 return result.GetLastError{}, err
103 }
104
105 rdr, err := cmd.RoundTrip(ctx, description.SelectedServer{}, rw)
106 if err != nil {
107 return result.GetLastError{}, err
108 }
109
110 return gle.decode(rdr).Result()
111}