• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

evolvedbinary / elemental / 982

29 Apr 2025 08:34PM UTC coverage: 56.409% (+0.007%) from 56.402%
982

push

circleci

adamretter
[feature] Improve README.md badges

28451 of 55847 branches covered (50.94%)

Branch coverage included in aggregate %.

77468 of 131924 relevant lines covered (58.72%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.89
/exist-core/src/main/java/org/exist/util/io/MemoryMappedFileFilterInputStreamCache.java
1
/*
2
 * Elemental
3
 * Copyright (C) 2024, Evolved Binary Ltd
4
 *
5
 * admin@evolvedbinary.com
6
 * https://www.evolvedbinary.com | https://www.elemental.xyz
7
 *
8
 * Use of this software is governed by the Business Source License 1.1
9
 * included in the LICENSE file and at www.mariadb.com/bsl11.
10
 *
11
 * Change Date: 2028-04-27
12
 *
13
 * On the date above, in accordance with the Business Source License, use
14
 * of this software will be governed by the Apache License, Version 2.0.
15
 *
16
 * Additional Use Grant: Production use of the Licensed Work for a permitted
17
 * purpose. A Permitted Purpose is any purpose other than a Competing Use.
18
 * A Competing Use means making the Software available to others in a commercial
19
 * product or service that: substitutes for the Software; substitutes for any
20
 * other product or service we offer using the Software that exists as of the
21
 * date we make the Software available; or offers the same or substantially
22
 * similar functionality as the Software.
23
 */
24
package org.exist.util.io;
25

26
import java.io.IOException;
27
import java.io.InputStream;
28
import java.io.RandomAccessFile;
29
import java.nio.MappedByteBuffer;
30
import java.nio.channels.FileChannel;
31
import java.nio.file.Path;
32

33
/**
34
 * Cache implementation for CachingFilterInputStream Backed by a Memory Mapped
35
 * File
36
 *
37
 * @version 1.1
38
 *
39
 * @author <a href="mailto:adam.retter@googlemail.com">Adam Retter</a>
40
 * @author <a href="tobi.krebsATgmail.com">Tobi Krebs</a>
41
 */
42
public class MemoryMappedFileFilterInputStreamCache extends AbstractFilterInputStreamCache {
43

44
    private final static long DEFAULT_MEMORY_MAP_SIZE = 64 * 1024 * 1024; //64MB
45

46
    private final RandomAccessFile raf;
47
    private final FileChannel channel;
48
    private MappedByteBuffer buf;
49
    private Path tempFile = null;
1✔
50
    private final long memoryMapSize = DEFAULT_MEMORY_MAP_SIZE;
1✔
51

52
    private boolean externalFile = true;
1✔
53

54
    public MemoryMappedFileFilterInputStreamCache(final InputStream src) throws IOException {
55
        this(src, null);
1✔
56
    }
1✔
57

58
    public MemoryMappedFileFilterInputStreamCache(final InputStream src, final Path f) throws IOException {
59
        super(src);
1✔
60

61
        if(f == null) {
1!
62
            tempFile = TemporaryFileManager.getInstance().getTemporaryFile();
1✔
63
            externalFile = false;
1✔
64
        } else {
1✔
65
            tempFile = f;
×
66
            externalFile = true;
×
67
        }
68

69
        /**
70
         * Check the applicability of these bugs to this code:
71
         * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038
72
         * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6417205 (fixed in
73
         * 1.6)
74
         */
75

76
        this.raf = new RandomAccessFile(tempFile.toFile(), "rw");   //TODO(AR) consider moving to Files.newByteChannel(tempFile)
1✔
77
        this.channel = raf.getChannel();
1✔
78
        this.buf = channel.map(FileChannel.MapMode.READ_WRITE, 0, getMemoryMapSize());
1✔
79
    }
1✔
80

81
    private long getMemoryMapSize() {
82
        return memoryMapSize;
1✔
83
    }
84

85
    private void increaseSize(final long bytes) throws IOException {
86

87
        long factor = (bytes / getMemoryMapSize());
×
88
        if (factor == 0 || bytes % getMemoryMapSize() > 0) {
×
89
            factor++;
×
90
        }
91

92
        buf.force();
×
93

94
        //TODO revisit this based on the comment below, I now believe setting position in map does work, but you have to have the correct offset added in as well! Adam
95
        final int position = buf.position();
×
96
        buf = channel.map(FileChannel.MapMode.READ_WRITE, 0, buf.capacity() + (getMemoryMapSize() * factor));
×
97
        buf.position(position); //setting the position in the map() call above does not seem to work!
×
98
        //bufAccessor.refresh();
99
    }
×
100

101
    @Override
102
    public void write(final byte[] b, final int off, final int len) throws IOException {
103

104
        if (buf.remaining() < len) {
1!
105
            //we need to remap the file
106
            increaseSize(len - buf.remaining());
×
107
        }
108

109
        buf.put(b, off, len);
1✔
110
    }
1✔
111

112
    @Override
113
    public void write(final int i) throws IOException {
114

115
        if (buf.remaining() < 1) {
1!
116
            //we need to remap the file
117
            increaseSize(1);
×
118
        }
119

120
        buf.put((byte) i);
1✔
121
    }
1✔
122

123
    @Override
124
    public byte get(final int off) throws IOException {
125

126
        if (off > buf.capacity()) {
1!
127
            //we need to remap the file
128
            increaseSize(off - buf.capacity());
×
129
        }
130

131
        return buf.get(off);
1✔
132
    }
133

134
    @Override
135
    public int getLength() {
136
        return buf.capacity() - buf.remaining();
1✔
137
    }
138

139
    @Override
140
    public void copyTo(final int cacheOffset, final byte[] b, final int off, final int len) throws IOException {
141

142
        if (off + len > buf.capacity()) {
1!
143
            //we need to remap the file
144
            increaseSize(off + len - buf.capacity());
×
145
        }
146

147
        //get the current position
148
        final int position = buf.position();
1✔
149

150
        try {
151
            //move to the offset
152
            buf.position(cacheOffset);
1✔
153

154
            //read the data;
155
            final byte[] data = new byte[len];
1✔
156
            buf.get(data, 0, len);
1✔
157

158
            System.arraycopy(data, 0, b, off, len);
1✔
159
        } finally {
1✔
160
            //reset the position
161
            buf.position(position);
1✔
162
        }
163
    }
1✔
164

165
    @Override
166
    public void invalidate() throws IOException {
167
        buf.force();
1✔
168
        channel.close();
1✔
169
        raf.close();
1✔
170
        //System.gc();
171

172
        if (tempFile != null && (!externalFile)) {
1!
173
            TemporaryFileManager.getInstance().returnTemporaryFile(tempFile);
1✔
174
        }
175
    }
1✔
176

177
    /**
178
     * Get the path of the file backing the cache.
179
     *
180
     * @return the path of the file backing the cache.
181
     */
182
    public Path getFilePath() {
183
        return tempFile;
×
184
    }
185
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc