Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (C) 2011 the original author or authors. See the notice.md file distributed with this work for additional information regarding copyright ownership. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
 
 package org.iq80.leveldb.impl;
 
 
 import java.io.File;
 
 import static org.iq80.leveldb.impl.LogConstants.BLOCK_SIZE;
 import static org.iq80.leveldb.impl.LogConstants.HEADER_SIZE;
 
 public class FileChannelLogWriter implements LogWriter
 {
     private final File file;
     private final long fileNumber;
     private final FileChannel fileChannel;
     private final AtomicBoolean closed = new AtomicBoolean();

    
Current offset in the current block
 
     private int blockOffset;
 
     public FileChannelLogWriter(File filelong fileNumber)
             throws FileNotFoundException
     {
         Preconditions.checkNotNull(file"file is null");
         Preconditions.checkArgument(fileNumber >= 0, "fileNumber is negative");
 
         this. = file;
         this. = fileNumber;
         this. = new FileOutputStream(file).getChannel();
     }
 
     @Override
     public boolean isClosed()
     {
         return .get();
     }
 
     @Override
     public synchronized void close()
     {
         .set(true);
 
         // try to forces the log to disk
         try {
             .force(true);
         }
         catch (IOException ignored) {
         }
 
         // close the channel
         Closeables.closeQuietly();
     }
 
     @Override
     public synchronized void delete()
     {
         .set(true);
 
         // close the channel
         Closeables.closeQuietly();
 
         // try to delete the file
         .delete();
     }
 
     @Override
     public File getFile()
     {
         return ;
     }
    @Override
    public long getFileNumber()
    {
        return ;
    }
    // Writes a stream of chunks such that no chunk is split across a block boundary
    @Override
    public synchronized void addRecord(Slice recordboolean force)
            throws IOException
    {
        Preconditions.checkState(!.get(), "Log has been closed");
        SliceInput sliceInput = record.input();
        // used to track first, middle and last blocks
        boolean begin = true;
        // Fragment the record int chunks as necessary and write it.  Note that if record
        // is empty, we still want to iterate once to write a single
        // zero-length chunk.
        do {
            int bytesRemainingInBlock =  - ;
            Preconditions.checkState(bytesRemainingInBlock >= 0);
            // Switch to a new block if necessary
            if (bytesRemainingInBlock < ) {
                if (bytesRemainingInBlock > 0) {
                    // Fill the rest of the block with zeros
                    // todo lame... need a better way to write zeros
                    .write(ByteBuffer.allocate(bytesRemainingInBlock));
                }
                 = 0;
                bytesRemainingInBlock =  - ;
            }
            // Invariant: we never leave less than HEADER_SIZE bytes available in a block
            int bytesAvailableInBlock = bytesRemainingInBlock - ;
            Preconditions.checkState(bytesAvailableInBlock >= 0);
            // if there are more bytes in the record then there are available in the block,
            // fragment the record; otherwise write to the end of the record
            boolean end;
            int fragmentLength;
            if (sliceInput.available() > bytesAvailableInBlock) {
                end = false;
                fragmentLength = bytesAvailableInBlock;
            }
            else {
                end = true;
                fragmentLength = sliceInput.available();
            }
            // determine block type
            LogChunkType type;
            if (begin && end) {
                type = .;
            }
            else if (begin) {
                type = .;
            }
            else if (end) {
                type = .;
            }
            else {
                type = .;
            }
            // write the chunk
            writeChunk(typesliceInput.readSlice(fragmentLength));
            // we are no longer on the first chunk
            begin = false;
        } while (sliceInput.isReadable());
        if (force) {
            .force(false);
        }
    }
    private void writeChunk(LogChunkType typeSlice slice)
            throws IOException
    {
        Preconditions.checkArgument(slice.length() <= 0xffff, "length %s is larger than two bytes"slice.length());
        Preconditions.checkArgument( +  <= );
        // create header
        Slice header = newLogRecordHeader(typesliceslice.length());
        // write the header and the payload
        header.getBytes(0, header.length());
        slice.getBytes(0, slice.length());
         +=  + slice.length();
    }
    private Slice newLogRecordHeader(LogChunkType typeSlice sliceint length)
    {
        int crc = Logs.getChunkChecksum(type.getPersistentId(), slice.getRawArray(), slice.getRawOffset(), length);
        // Format the header
        SliceOutput header = Slices.allocate().output();
        header.writeInt(crc);
        header.writeByte((byte) (length & 0xff));
        header.writeByte((byte) (length >>> 8));
        header.writeByte((byte) (type.getPersistentId()));
        return header.slice();
    }
New to GrepCode? Check out our FAQ X