1 2 /** 3 * Copyright (C) 2018-present MongoDB, Inc. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the Server Side Public License, version 1, 7 * as published by MongoDB, Inc. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * Server Side Public License for more details. 13 * 14 * You should have received a copy of the Server Side Public License 15 * along with this program. If not, see 16 * <http://www.mongodb.com/licensing/server-side-public-license>. 17 * 18 * As a special exception, the copyright holders give permission to link the 19 * code of portions of this program with the OpenSSL library under certain 20 * conditions as described in each individual source file and distribute 21 * linked combinations including the program with the OpenSSL library. You 22 * must comply with the Server Side Public License in all respects for 23 * all of the code used other than as permitted herein. If you modify file(s) 24 * with this exception, you may extend this exception to your version of the 25 * file(s), but you are not obligated to do so. If you do not wish to do so, 26 * delete this exception statement from your version. If you delete this 27 * exception statement from all source files in the program, then also delete 28 * it in the license file. 29 */ 30 31 #pragma once 32 33 #include <boost/optional.hpp> 34 35 #include "mongo/db/ops/write_ops.h" 36 #include "mongo/s/chunk_version.h" 37 #include "mongo/stdx/memory.h" 38 #include "mongo/util/net/op_msg.h" 39 40 namespace mongo { 41 42 /** 43 * This class wraps the different kinds of command requests into a generically usable write command 44 * request that can be passed around. 45 */ 46 class BatchedCommandRequest { 47 public: 48 enum BatchType { BatchType_Insert, BatchType_Update, BatchType_Delete }; 49 BatchedCommandRequest(write_ops::Insert insertOp)50 BatchedCommandRequest(write_ops::Insert insertOp) 51 : _batchType(BatchType_Insert), 52 _insertReq(stdx::make_unique<write_ops::Insert>(std::move(insertOp))) {} 53 BatchedCommandRequest(write_ops::Update updateOp)54 BatchedCommandRequest(write_ops::Update updateOp) 55 : _batchType(BatchType_Update), 56 _updateReq(stdx::make_unique<write_ops::Update>(std::move(updateOp))) {} 57 BatchedCommandRequest(write_ops::Delete deleteOp)58 BatchedCommandRequest(write_ops::Delete deleteOp) 59 : _batchType(BatchType_Delete), 60 _deleteReq(stdx::make_unique<write_ops::Delete>(std::move(deleteOp))) {} 61 62 BatchedCommandRequest(BatchedCommandRequest&&) = default; 63 64 static BatchedCommandRequest parseInsert(const OpMsgRequest& request); 65 static BatchedCommandRequest parseUpdate(const OpMsgRequest& request); 66 static BatchedCommandRequest parseDelete(const OpMsgRequest& request); 67 getBatchType()68 BatchType getBatchType() const { 69 return _batchType; 70 } 71 72 const NamespaceString& getNS() const; 73 NamespaceString getTargetingNS() const; 74 75 /** 76 * Index creation can be expressed as an insert into the 'system.indexes' namespace. 77 */ 78 bool isInsertIndexRequest() const; 79 getInsertRequest()80 const auto& getInsertRequest() const { 81 invariant(_insertReq); 82 return *_insertReq; 83 } 84 getUpdateRequest()85 const auto& getUpdateRequest() const { 86 invariant(_updateReq); 87 return *_updateReq; 88 } 89 getDeleteRequest()90 const auto& getDeleteRequest() const { 91 invariant(_deleteReq); 92 return *_deleteReq; 93 } 94 95 std::size_t sizeWriteOps() const; 96 setWriteConcern(const BSONObj & writeConcern)97 void setWriteConcern(const BSONObj& writeConcern) { 98 _writeConcern = writeConcern.getOwned(); 99 } 100 hasWriteConcern()101 bool hasWriteConcern() const { 102 return _writeConcern.is_initialized(); 103 } 104 getWriteConcern()105 const BSONObj& getWriteConcern() const { 106 invariant(_writeConcern); 107 return *_writeConcern; 108 } 109 110 bool isVerboseWC() const; 111 setShardVersion(ChunkVersion shardVersion)112 void setShardVersion(ChunkVersion shardVersion) { 113 _shardVersion = std::move(shardVersion); 114 } 115 hasShardVersion()116 bool hasShardVersion() const { 117 return _shardVersion.is_initialized(); 118 } 119 getShardVersion()120 const ChunkVersion& getShardVersion() const { 121 invariant(_shardVersion); 122 return *_shardVersion; 123 } 124 125 const write_ops::WriteCommandBase& getWriteCommandBase() const; 126 void setWriteCommandBase(write_ops::WriteCommandBase writeCommandBase); 127 128 void serialize(BSONObjBuilder* builder) const; 129 BSONObj toBSON() const; 130 std::string toString() const; 131 132 /** 133 * Generates a new request, the same as the old, but with insert _ids if required. 134 */ 135 static BatchedCommandRequest cloneInsertWithIds(BatchedCommandRequest origCmdRequest); 136 137 private: 138 BatchType _batchType; 139 140 std::unique_ptr<write_ops::Insert> _insertReq; 141 std::unique_ptr<write_ops::Update> _updateReq; 142 std::unique_ptr<write_ops::Delete> _deleteReq; 143 144 boost::optional<ChunkVersion> _shardVersion; 145 146 boost::optional<BSONObj> _writeConcern; 147 }; 148 149 /** 150 * Similar to above, this class wraps the write items of a command request into a generically 151 * usable type. Very thin wrapper, does not own the write item itself. 152 * 153 * TODO: Use in BatchedCommandRequest above 154 */ 155 class BatchItemRef { 156 public: BatchItemRef(const BatchedCommandRequest * request,int itemIndex)157 BatchItemRef(const BatchedCommandRequest* request, int itemIndex) 158 : _request(request), _itemIndex(itemIndex) {} 159 getRequest()160 const BatchedCommandRequest* getRequest() const { 161 return _request; 162 } 163 getItemIndex()164 int getItemIndex() const { 165 return _itemIndex; 166 } 167 getOpType()168 BatchedCommandRequest::BatchType getOpType() const { 169 return _request->getBatchType(); 170 } 171 getDocument()172 const auto& getDocument() const { 173 dassert(_itemIndex < static_cast<int>(_request->sizeWriteOps())); 174 return _request->getInsertRequest().getDocuments().at(_itemIndex); 175 } 176 getUpdate()177 const auto& getUpdate() const { 178 dassert(_itemIndex < static_cast<int>(_request->sizeWriteOps())); 179 return _request->getUpdateRequest().getUpdates().at(_itemIndex); 180 } 181 getDelete()182 const auto& getDelete() const { 183 dassert(_itemIndex < static_cast<int>(_request->sizeWriteOps())); 184 return _request->getDeleteRequest().getDeletes().at(_itemIndex); 185 } 186 187 private: 188 const BatchedCommandRequest* _request; 189 const int _itemIndex; 190 }; 191 192 } // namespace mongo 193