我的家園

          我的家園
            在之前的源代碼分析中我們經常遇到神秘的 OutMessage 類的實例,并調用它的 writeInt,query 等方法與 MongoDB 數據庫進行交互。
            但 OutMessage 繼承了 BSONEncoder 類,而 BSONEncoder 的 writeInt 等方法實際上是委托給 OutputBuffer 類的實例執行的。
            因此為了弄清楚 OutMessage 類的實例的行為,我們需要先了解 OutputBuffer 類的主要邏輯。

          BasicOutputBuffer 和 PoolOutputBuffer 的 write 和 pipe 方法的實現

            OutputBuffer 類是一個抽象類,有兩個子類: BasicOutputBuffer 和 PoolOutputBuffer。
            OutputBuffer 的作用是緩沖對將要寫入到輸出流中的數據進行緩沖,準備好后通過 pipe 方法將數據輸出到輸出流中。

            子類主要實現了抽象方法 write 和 pipe:
          public abstract void write(byte[] b, int off, int len);
          public abstract void write(int b);
          public abstract int pipe( OutputStream out );
          

            BasicOutputBuffer 類的 write 方法的實現如下:
              // 寫入數據到緩沖區
              public void write(byte[] b, int off, int len){
                  // 保證緩沖區空間足夠
                  // 不夠則開辟新的空間
                  _ensure( len );
          
                  // 復制數據到緩沖區
                  System.arraycopy( b , off , _buffer , _cur , len );
          
                  // 改變代表偏移量和緩沖區大小的數字
                  _cur += len;
                  _size = Math.max( _cur , _size );
              }
          
              // 保證緩沖區空間足夠
              // 不夠則開辟新的空間
              void _ensure( int more ){
                  // 計算需要的大小
                  final int need = _cur + more;
          
                  // 目前的緩沖區大小足夠。
                  // 不再開辟新的空間
                  if ( need < _buffer.length )
                      return;
          
                  // 新的緩沖區大小是原來的兩倍
                  int newSize = _buffer.length*2;
                  // 如果仍然不夠,開辟更大的空間
                  if ( newSize <= need )
                      newSize = need + 128;
          
                  // 創建數組
                  byte[] n = new byte[newSize];
                  // 將緩沖區中數據復制到數組中
                  System.arraycopy( _buffer , 0 , n , 0 , _size );
                  // 以新的數組作為緩沖區
                  _buffer = n;
              }
          
              // 只寫入一個字節
              public void write(int b){
                  // 保證有一個字節的空間
                  _ensure(1);
                  // 將 int 型數據的低 8 位保存到緩沖區
                  _buffer[_cur++] = (byte)(0xFF&b);
                  // 修改表示緩沖區數據大小的數值
                  _size = Math.max( _cur , _size );
              }
          

          BasicOutputBuffer 類的 pipe 方法的實現如下:
              public int pipe( OutputStream out )
                  throws IOException {
                  // 將緩沖區中的數據寫入輸出流中
                  out.write( _buffer , 0 , _size );
          
                  // 返回緩沖區大小
                  return _size;
              }
          

          PoolOutputBuffer 類的 write 方法實現如下:
              public void write(byte[] b, int off, int len){
                  while ( len > 0 ){
                      // 獲取一塊當前緩沖區空間
                      byte[] bs = _cur();
                      // 計算本次寫入大小
                      int space = Math.min( bs.length - _cur.y , len );
                      // 將數據復制緩沖區
                      System.arraycopy( b , off , bs , _cur.y , space );
          
                      // 修改偏移量等后續工作
                      _cur.inc( space );
                      len -= space;
                      off += space;
          
                      // 其他后續處理
                      // 如緩沖區滿時,創建下一個緩沖區塊等
                      _afterWrite();
                  }
              }
          
              // 只寫入一個字節
              public void write(int b){
                  // 獲取緩沖區空間
                  byte[] bs = _cur();
                  // 將 int 型數值的低 8 為保存到緩沖區
                  bs[_cur.getAndInc()] = (byte)(b&0xFF);
                  // 后續處理
                  _afterWrite();
              }
          

          PoolOutputBuffer 類的 pipe 方法實現如下:
              public int pipe( OutputStream out )
                  throws IOException {
                  
                  if ( out == null )
                      throw new NullPointerException( "out is null" );
          
                  int total = 0;
                  
                  for ( int i=-1; i<_fromPool.size(); i++ ){
                      // 獲取對象池中指定索引的數據
                      byte[] b = _get( i );
                      // 獲取對象池中指定索引的數據的大小
                      int amt = _end.len( i );
          
                      // 將數據寫入到輸出流中
                      out.write( b , 0 , amt );
          
                      // 增加表示總數據大小的數值
                      total += amt;
                  }
                  
                  return total;
              }
          

          OutputBuffer 類的 write* 方法

          基于子類實現的 write 方法,OutputBuffer 實現了一系列 write* 方法
              // 寫入 int 型
              public void writeInt( int x ){
                  // 寫入第 1 個字節(第 1 - 8 位)
                  write( x >> 0 );
                  // 寫入第 2 個字節(第 9 - 16 位)
                  write( x >> 8 );
                  // 寫入第 3 個字節(第 17 - 24 位)
                  write( x >> 16 );
                  // 寫入第 4 個字節(第 25 - 32 位)
                  write( x >> 24 );
              }
          
              // 按“大端”(Big End) 法 寫入 int 型
              public void writeIntBE( int x ){
                  // 寫入第 4 個字節(第 25 - 32 位)
                  write( x >> 24 );
                  // 寫入第 3 個字節(第 17 - 24 位)
                  write( x >> 16 );
                  // 寫入第 2 個字節(第 9 - 16 位)
                  write( x >> 8 );
                  // 寫入第 1 個字節(第 1 - 8 位)
                  write( x );
              }
          
              // 指定位置寫入 int 型數據
              public void writeInt( int pos , int x ){
                  // 獲取當前位置
                  final int save = getPosition();
                  // 設置當前位置
                  setPosition( pos );
                  // 寫入 int 型數據
                  writeInt( x );
                  // 恢復當前位置
                  setPosition( save );
              }
          
              // 寫入 long 型數值
              public void writeLong( long x ){
                  // 寫入第 1 個字節(第 1 - 8 位)
                  write( (byte)(0xFFL & ( x >> 0 ) ) );
                  // 寫入第 2 個字節(第 9 - 16 位)
                  write( (byte)(0xFFL & ( x >> 8 ) ) );
                  // 寫入第 3 個字節(第 17 - 24 位)
                  write( (byte)(0xFFL & ( x >> 16 ) ) );
                  // 寫入第 4 個字節(第 25 - 32 位)
                  write( (byte)(0xFFL & ( x >> 24 ) ) );
                  // 寫入第 5 個字節(第 33 - 40 位)
                  write( (byte)(0xFFL & ( x >> 32 ) ) );
                  // 寫入第 6 個字節(第 41 - 48 位)
                  write( (byte)(0xFFL & ( x >> 40 ) ) );
                  // 寫入第 7 個字節(第 49 - 56 位)
                  write( (byte)(0xFFL & ( x >> 48 ) ) );
                  // 寫入第 8 個字節(第 57 - 64 位)
                  write( (byte)(0xFFL & ( x >> 56 ) ) );
              }
          
              // 寫入 double 型數值
              public void writeDouble( double x ){
                  // 將 double 型轉為 long 型 (IEEE 754 表示法) 后寫入
                  writeLong( Double.doubleToRawLongBits( x ) );
              }
          





          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 安乡县| 若尔盖县| 确山县| 手游| 江达县| 浙江省| 普安县| 白沙| 岱山县| 云安县| 江华| 浙江省| 奉化市| 庆云县| 茂名市| 石棉县| 筠连县| 新郑市| 上杭县| 敖汉旗| 维西| 昌吉市| 剑阁县| 云梦县| 五河县| 沧源| 勐海县| 朝阳市| 广宁县| 高邑县| 重庆市| 双辽市| 曲靖市| 新疆| 德保县| 清原| 江源县| 张家港市| 上饶市| 栾川县| 南阳市|