Uploaded image for project: 'C Driver'
  1. C Driver
  2. CDRIVER-110

support sending mongo messages on network without additional malloc where available

    • Type: Icon: Improvement Improvement
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 0.90.0
    • Affects Version/s: 0.4
    • Component/s: None
    • Environment:
      Linux, Windows

      I understand that the C driver has broad compatibility as a specific goal, but easy platform-specific optimizations can be very useful.

      Functions like mongo_insert() currently include a call to mongo_message_create() which then calls bson_malloc(). This supports the requirement to transmit the existing bson data prefixed by the collection name in a single send() call on the socket.

      Linux and Windows both support the required network semantics without the additional bson_malloc() by using vector-oriented send() equivalents.

      Here is a simplified example :

      int mongo_insert_bson( mongo * pMongo, const char * pCollection, bson * pBSON )
      {
      #if defined( linux ) || defined( _WIN32 )
      mongo_header header ;

      int nBSON = *( ( int32_t * ) pBSON->data ) ;
      int nCollection = 1 + strlen( pCollection ) ;

      header.len = sizeof( header ) + sizeof( ZERO ) + nCollection + nBSON ;
      header.op = MONGO_OP_INSERT ;
      header.id = rand() ;
      header.responseTo = 0 ;

      #if defined( _WIN32 )
      {
      WSABUF pSend[ 3 ] ;
      int nSent ;

      pSend[ 0 ].len = sizeof( header ) ;
      pSend[ 0 ].buf = ( char * ) &( header ) ;

      if( 0 != WSASend( pMongo->sock, pSend, 1, &( nSent ), 0, 0, 0 ) )

      { pMongo->err = MONGO_IO_ERROR ; return MONGO_ERROR ; }

      pSend[ 0 ].len = sizeof( ZERO ) ;
      pSend[ 0 ].buf = ( char * ) &( ZERO ) ;

      pSend[ 1 ].len = nCollection ;
      pSend[ 1 ].buf = ( char * ) pCollection ;

      pSend[ 2 ].len = nBSON ;
      pSend[ 2 ].buf = ( char * ) pBSON->data ;

      if( 0 != WSASend( pMongo->sock, pSend, 3, &( nSent ), 0, 0, 0 ) )
      { pMongo->err = MONGO_IO_ERROR ; return MONGO_ERROR ; }

      return MONGO_OK ;
      }
      #endif // defined( _WIN32 )

      #if defined( linux )
      {
      struct iovec pSend[ 3 ] ;

      ssize_t nSent ;

      pSend[ 0 ].iov_len = sizeof( header ) ;
      pSend[ 0 ].iov_base = &( header ) ;

      if( 1 == ( nSent = writev( pMongo>sock, pSend, 1 ) ) )

      { pMongo->err = MONGO_IO_ERROR ; return MONGO_ERROR ; }

      pSend[ 0 ].iov_len = sizeof( ZERO ) ;
      pSend[ 0 ].iov_base = &( ZERO ) ;

      pSend[ 1 ].iov_len = nCollection ;
      pSend[ 1 ].iov_base = pCollection ;

      pSend[ 2 ].iov_len = nBSON ;
      pSend[ 2 ].iov_base = pBSON->data ;

      if( 1 == ( nSent = writev( pMongo>sock, pSend, 3 ) ) )
      { pMongo->err = MONGO_IO_ERROR ; return MONGO_ERROR ; }

      return MONGO_OK ;
      }
      #endif // defined( _WIN32 )

      #else
      return mongo_insert( pMongo, pCollection, pBSON ) ;

      #endif // defined( linux ) || defined( _WIN32 )

      } // mongo_insert()

      Incorporating this kind of optimization generically in the mongo C driver probably requires a fair amount of well-considered refactoring, so I am not just sending in a hasty patch. I am, however, more than happy to collaborate on this effort.

            Assignee:
            gjmurakami Gary Murakami
            Reporter:
            gifford Gifford Hesketh
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: