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 "mongo/db/exec/working_set.h" 34 #include "mongo/util/unowned_ptr.h" 35 36 namespace mongo { 37 38 class CanonicalQuery; 39 class Collection; 40 class OperationContext; 41 class SeekableRecordCursor; 42 43 class WorkingSetCommon { 44 public: 45 /** 46 * Get an owned copy of the BSONObj the WSM refers to. 47 * Requires either a valid BSONObj or valid RecordId. 48 * Returns true if the fetch and invalidate succeeded, false otherwise. 49 */ 50 static bool fetchAndInvalidateRecordId(OperationContext* opCtx, 51 WorkingSetMember* member, 52 const Collection* collection); 53 54 /** 55 * This must be called as part of "saveState" operations after all nodes in the tree save their 56 * state. 57 * 58 * Iterates over WorkingSetIDs in 'workingSet' which are "sensitive to yield". These are ids 59 * that have transitioned into the RID_AND_IDX state since the previous yield. 60 * 61 * The RID_AND_IDX members are tagged as suspicious so that they can be handled properly in case 62 * the document keyed by the index key is deleted or updated during the yield. 63 */ 64 static void prepareForSnapshotChange(WorkingSet* workingSet); 65 66 /** 67 * Transitions the WorkingSetMember with WorkingSetID 'id' from the RID_AND_IDX state to the 68 * RID_AND_OBJ state by fetching a document. Does the fetch using 'cursor'. 69 * 70 * If false is returned, the document should not be considered for the result set. It is the 71 * caller's responsibility to free 'id' in this case. 72 * 73 * WriteConflict exceptions may be thrown. When they are, 'member' will be unmodified. 74 */ 75 static bool fetch(OperationContext* opCtx, 76 WorkingSet* workingSet, 77 WorkingSetID id, 78 unowned_ptr<SeekableRecordCursor> cursor); 79 fetchIfUnfetched(OperationContext * opCtx,WorkingSet * workingSet,WorkingSetID id,unowned_ptr<SeekableRecordCursor> cursor)80 static bool fetchIfUnfetched(OperationContext* opCtx, 81 WorkingSet* workingSet, 82 WorkingSetID id, 83 unowned_ptr<SeekableRecordCursor> cursor) { 84 WorkingSetMember* member = workingSet->get(id); 85 if (member->hasObj()) 86 return true; 87 return fetch(opCtx, workingSet, id, cursor); 88 } 89 90 /** 91 * Build a BSONObj which represents a Status to return in a WorkingSet. 92 */ 93 static BSONObj buildMemberStatusObject(const Status& status); 94 95 /** 96 * Allocate a new WSM and initialize it with 97 * the code and reason from the status. 98 * Owned BSON object will have the following layout: 99 * { 100 * ok: <ok>, // 1 for OK; 0 otherwise. 101 * code: <code>, // Status::code() 102 * errmsg: <errmsg> // Status::reason() 103 * } 104 */ 105 static WorkingSetID allocateStatusMember(WorkingSet* ws, const Status& status); 106 107 /** 108 * Returns true if object was created by allocateStatusMember(). 109 */ 110 static bool isValidStatusMemberObject(const BSONObj& obj); 111 112 /** 113 * Returns object in working set member created with allocateStatusMember(). 114 * Does not assume isValidStatusMemberObject. 115 * If the WSID is invalid or the working set member is created by 116 * allocateStatusMember, objOut will not be updated. 117 */ 118 static void getStatusMemberObject(const WorkingSet& ws, WorkingSetID wsid, BSONObj* objOut); 119 120 /** 121 * Returns status from working set member object. 122 * Assumes isValidStatusMemberObject(). 123 */ 124 static Status getMemberObjectStatus(const BSONObj& memberObj); 125 126 /** 127 * Returns status from working set member created with allocateStatusMember(). 128 * Assumes isValidStatusMemberObject(). 129 */ 130 static Status getMemberStatus(const WorkingSetMember& member); 131 132 /** 133 * Formats working set member object created with allocateStatusMember(). 134 */ 135 static std::string toStatusString(const BSONObj& obj); 136 }; 137 138 } // namespace mongo 139