我的家園

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

          BasicOutputBuffer 和 PoolOutputBuffer 的 write 和 pipe 方法的實(shí)現(xiàn)

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

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

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

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

          PoolOutputBuffer 類的 pipe 方法實(shí)現(xiàn)如下:
              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++ ){
                      // 獲取對象池中指定索引的數(shù)據(jù)
                      byte[] b = _get( i );
                      // 獲取對象池中指定索引的數(shù)據(jù)的大小
                      int amt = _end.len( i );
          
                      // 將數(shù)據(jù)寫入到輸出流中
                      out.write( b , 0 , amt );
          
                      // 增加表示總數(shù)據(jù)大小的數(shù)值
                      total += amt;
                  }
                  
                  return total;
              }
          

          OutputBuffer 類的 write* 方法

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





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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 麟游县| 盖州市| 昭平县| 察哈| 曲靖市| 康保县| 古丈县| 安阳县| 卓尼县| 信宜市| 疏附县| 法库县| 海林市| 古交市| 嵊州市| 平遥县| 麟游县| 鹤峰县| 翁源县| 呼伦贝尔市| 济南市| 新闻| 绥宁县| 无锡市| 祁连县| 永新县| 皮山县| 巩义市| 宿松县| 沙坪坝区| 武宁县| 临武县| 眉山市| 庆阳市| 静海县| 扎赉特旗| 天全县| 丹巴县| 利川市| 高密市| 磐安县|