Mongodb源码分析--删除记录

在之前的一篇文章 中,介绍了assembleResponse函数(位于instance.cpp第224行),它会根据op操作枚举类型来调用相应的crud操作,枚举类型定义如下:

 

   enum  Operations {
        opReply  =   1 ,      /*  reply. responseTo is set.  */
        dbMsg  =   1000 ,     /*  generic msg command followed by a string  */
        dbUpdate  =   2001 /*  update object  */
        dbInsert  =   2002 ,
        
// dbGetByOID = 2003,
        dbQuery  =   2004 ,
        dbGetMore  =   2005 ,
        dbDelete  =   2006 ,
        dbKillCursors  =   2007
    };


    可以看到dbDelete = 2002 为删除操作枚举值。当客户端将要删除的记录(或条件的document)发到服务端之后,mongodb通过消息封装方式将数据包中的字节流解析转成 message类型,并进一步转换成dbmessage之后,mongodb就会根据消息类型进行判断,以决定接下来执行的操作),下面我们看一下 assembleResponse在确定是删除操作时调用的方法,如下:

 assembleResponse( Message  & m, DbResponse  & dbresponse,  const  SockAddr  & client ) {
    .....
            
try  {
                
if  ( op  ==  dbInsert ) {   // 添加记录操作
                    receivedInsert(m, currentOp);
                }
                
else   if  ( op  ==  dbUpdate ) {  // 更新记录
                    receivedUpdate(m, currentOp);
                }
                
else   if  ( op  ==  dbDelete ) {  // 删除记录
                    receivedDelete(m, currentOp);
                }
                
else   if  ( op  ==  dbKillCursors ) {  // 删除Cursors(游标)对象
                    currentOp.ensureStarted();
                    logThreshold  =   10 ;
                    ss  <<   " killcursors  " ;
                    receivedKillCursors(m);
                }
                
else  {
                    mongo::log()  <<   "     operation isn't supported:  "   <<  op  <<  endl;
                    currentOp.done();
                    log  =   true ;
                }
            }
          .....
        }
    }


    从上面代码可以看出,系统在确定dbDelete操作时,调用了receivedDelete()方法(位于instance.cpp文件第323行),下面是该方法的定义:

 

void  receivedDelete(Message &  m, CurOp &  op) {
        DbMessage d(m);
// 将Message消息转换成数据库消息格式
         const   char   * ns  =  d.getns(); // 获取相应名空间信息
        assert( * ns);
        uassert( 
10056  ,   " not master " , isMasterNs( ns ) ); // 因为CUD操作在主库中操作,所以这里断言名空间包含的db信息中是不是主库,即"master"
        op.debug().str  <<
        ns 
<<   '   ' ;
        
// 获取"删除消息"结构体中的flags 标识位,如设置了该位,则仅删除查找到的第一条记录(document),否则删除所有匹配记录.
        
// 关于消息结构体,参见我的这篇文章: http://www.cnblogs.com/daizhj/archive/2011/04/02/2003335.html
         int  flags  =  d.pullInt(); //
         bool  justOne  =  flags  &  RemoveOption_JustOne;
        
bool  broadcast  =  flags  &  RemoveOption_Broadcast;
        assert( d.moreJSObjs() );
        BSONObj pattern 
=  d.nextJsObj(); // 获取"删除消息"结构体中的selector(也就是要删数据条件where)
        {
            
string  s  =  pattern.toString();
            op.debug().str 
<<   "  query:  "   <<  s;
            op.setQuery(pattern);
        }

        writelock lk(ns);
        
//  如果不更新所有节点(sharding)且当前物理结点是shard 状态时
         if  (  !  broadcast  &  handlePossibleShardedMessage( m ,  0  ) )
            
return ;
        
// if this ever moves to outside of lock, need to adjust check Client::Context::_finishInit
        Client::Context ctx(ns);

        
long   long  n  =  deleteObjects(ns, pattern, justOne,  true ); // 删除对象信息
        lastError.getSafe() -> recordDelete( n );
    }


    上面方法主要是对消息中的flag信息进行解析,以获取消息中的删除条件等信息,并最终调用 deleteObjects方法,该方法位于query.cpp文件中,如下:   

     // query.cpp文件 128行
      /*  ns:      要删除的表集合(namespace, e.g. <database>.<collection>)
       pattern: 删除条件,相当于 "where" 字语(clause / criteria)
       justOne: 是否仅删除第一个匹配对象信息
       god:     是否允许访问系统名空间(system namespaces)
    
*/
    
long   long  deleteObjects( const   char   * ns, BSONObj pattern,  bool  justOneOrig,  bool  logop,  bool  god, RemoveSaver  *  rs ) {
        
if ! god ) { // 如果不能访问system空间,但却删除该空间信息时
             if  ( strstr(ns,  " .system. " ) ) {
                
/*  note a delete from system.indexes would corrupt the db. if done here, as there are pointers into those objects in NamespaceDetails.
                
*/
                uassert(
12050 " cannot delete from system namespace
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值