Remove atomix.storage.statistics
[controller.git] / third-party / atomix / storage / src / main / java / io / atomix / storage / buffer / MappedBytes.java
1 /*
2  * Copyright 2015-present Open Networking Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package io.atomix.storage.buffer;
17
18 import io.atomix.utils.memory.BufferCleaner;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.RandomAccessFile;
25 import java.nio.ByteBuffer;
26 import java.nio.MappedByteBuffer;
27 import java.nio.channels.FileChannel;
28 import java.nio.file.Files;
29
30 /**
31  * {@link ByteBuffer} based mapped bytes.
32  */
33 public class MappedBytes extends ByteBufferBytes {
34
35   private static final Logger LOGGER = LoggerFactory.getLogger(MappedBytes.class);
36
37   /**
38    * Allocates a mapped buffer in {@link FileChannel.MapMode#READ_WRITE} mode.
39    * <p>
40    * Memory will be mapped by opening and expanding the given {@link File} to the desired {@code count} and mapping the
41    * file contents into memory via {@link FileChannel#map(FileChannel.MapMode, long, long)}.
42    *
43    * @param file The file to map into memory. If the file doesn't exist it will be automatically created.
44    * @param size The count of the buffer to allocate (in bytes).
45    * @return The mapped buffer.
46    * @throws NullPointerException     If {@code file} is {@code null}
47    * @throws IllegalArgumentException If {@code count} is greater than {@link MappedBytes#MAX_SIZE}
48    * @see #allocate(File, FileChannel.MapMode, int)
49    */
50   public static MappedBytes allocate(File file, int size) {
51     return allocate(file, FileChannel.MapMode.READ_WRITE, size);
52   }
53
54   /**
55    * Allocates a mapped buffer.
56    * <p>
57    * Memory will be mapped by opening and expanding the given {@link File} to the desired {@code count} and mapping the
58    * file contents into memory via {@link FileChannel#map(FileChannel.MapMode, long, long)}.
59    *
60    * @param file The file to map into memory. If the file doesn't exist it will be automatically created.
61    * @param mode The mode with which to map the file.
62    * @param size The count of the buffer to allocate (in bytes).
63    * @return The mapped buffer.
64    * @throws NullPointerException     If {@code file} is {@code null}
65    * @throws IllegalArgumentException If {@code count} is greater than {@link Integer#MAX_VALUE}
66    * @see #allocate(File, int)
67    */
68   public static MappedBytes allocate(File file, FileChannel.MapMode mode, int size) {
69     return FileBytes.allocate(file, size).map(0, size, mode);
70   }
71
72   private final File file;
73   private final RandomAccessFile randomAccessFile;
74   private final FileChannel.MapMode mode;
75
76   protected MappedBytes(File file, RandomAccessFile randomAccessFile, MappedByteBuffer buffer, FileChannel.MapMode mode) {
77     super(buffer);
78     this.file = file;
79     this.randomAccessFile = randomAccessFile;
80     this.mode = mode;
81   }
82
83   @Override
84   protected ByteBuffer newByteBuffer(int size) {
85     try {
86       return randomAccessFile.getChannel().map(mode, 0, size);
87     } catch (IOException e) {
88       throw new RuntimeException(e);
89     }
90   }
91
92   @Override
93   public boolean isDirect() {
94     return true;
95   }
96
97   @Override
98   public Bytes flush() {
99     ((MappedByteBuffer) buffer).force();
100     return this;
101   }
102
103   @Override
104   public void close() {
105     try {
106       BufferCleaner.freeBuffer(buffer);
107     } catch (Exception e) {
108       if (LOGGER.isDebugEnabled()) {
109         LOGGER.debug("Failed to unmap direct buffer", e);
110       }
111     }
112     try {
113       randomAccessFile.close();
114     } catch (IOException e) {
115       throw new RuntimeException(e);
116     }
117     super.close();
118   }
119
120   /**
121    * Deletes the underlying file.
122    */
123   public void delete() {
124     try {
125       close();
126       Files.delete(file.toPath());
127     } catch (IOException e) {
128       throw new RuntimeException(e);
129     }
130   }
131
132   private static String parseMode(FileChannel.MapMode mode) {
133     if (mode == FileChannel.MapMode.READ_ONLY) {
134       return "r";
135     } else if (mode == FileChannel.MapMode.READ_WRITE) {
136       return "rw";
137     }
138     throw new IllegalArgumentException("unsupported map mode");
139   }
140
141 }