Import atomix/{storage,utils}
[controller.git] / third-party / atomix / utils / src / main / java / io / atomix / utils / memory / MappedMemory.java
1 /*
2  * Copyright 2017-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.utils.memory;
17
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 import java.io.File;
22 import java.nio.MappedByteBuffer;
23 import java.nio.channels.FileChannel;
24
25 /**
26  * Mapped memory.
27  * <p>
28  * This is a special memory descriptor that handles management of {@link MappedByteBuffer} based memory. The
29  * mapped memory descriptor simply points to the memory address of the underlying byte buffer. When memory is reallocated,
30  * the parent {@link MappedMemoryAllocator} is used to create a new {@link MappedByteBuffer}
31  * and free the existing buffer.
32  *
33  * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
34  */
35 public class MappedMemory implements Memory {
36   private static final long MAX_SIZE = Integer.MAX_VALUE - 5;
37
38   private static final Logger LOGGER = LoggerFactory.getLogger(MappedMemory.class);
39
40   /**
41    * Allocates memory mapped to a file on disk.
42    *
43    * @param file The file to which to map memory.
44    * @param size The count of the memory to map.
45    * @return The mapped memory.
46    * @throws IllegalArgumentException If {@code count} is greater than {@link MappedMemory#MAX_SIZE}
47    */
48   public static MappedMemory allocate(File file, int size) {
49     return new MappedMemoryAllocator(file).allocate(size);
50   }
51
52   /**
53    * Allocates memory mapped to a file on disk.
54    *
55    * @param file The file to which to map memory.
56    * @param mode The mode with which to map memory.
57    * @param size The count of the memory to map.
58    * @return The mapped memory.
59    * @throws IllegalArgumentException If {@code count} is greater than {@link MappedMemory#MAX_SIZE}
60    */
61   public static MappedMemory allocate(File file, FileChannel.MapMode mode, int size) {
62     if (size > MAX_SIZE) {
63       throw new IllegalArgumentException("size cannot be greater than " + MAX_SIZE);
64     }
65     return new MappedMemoryAllocator(file, mode).allocate(size);
66   }
67
68   private final MappedByteBuffer buffer;
69   private final MappedMemoryAllocator allocator;
70   private final int size;
71
72   public MappedMemory(MappedByteBuffer buffer, MappedMemoryAllocator allocator) {
73     this.buffer = buffer;
74     this.allocator = allocator;
75     this.size = buffer.capacity();
76   }
77
78   /**
79    * Flushes the mapped buffer to disk.
80    */
81   public void flush() {
82     buffer.force();
83   }
84
85   @Override
86   public int size() {
87     return size;
88   }
89
90   @Override
91   public void free() {
92     try {
93       BufferCleaner.freeBuffer(buffer);
94     } catch (Exception e) {
95       if (LOGGER.isDebugEnabled()) {
96         LOGGER.debug("Failed to unmap direct buffer", e);
97       }
98     }
99     allocator.release();
100   }
101
102   public void close() {
103     free();
104     allocator.close();
105   }
106 }