aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/fastlib/io/bufferedfile.h
blob: f6975c375d4a40344d26bde6299de4553fe759c8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include <vespa/vespalib/util/hdr_abort.h>
#include <vespa/vespalib/util/alloc.h>
#include <vespa/fastos/file.h>

/**
 * Provides buffered file access.
 */
class Fast_BufferedFile : public FastOS_FileInterface
{
private:
    using Alloc = vespalib::alloc::Alloc;
    /** The number of bytes left in the file. */
    int64_t _fileleft;
    /** Pointer to the start of the buffer. Correctly aligned for direct IO */
    Alloc _buf;
    /** Pointer to the input point in the buffer. */
    char *_bufi;
    /** Pointer to the end of the buffer. */
    char *_bufe;
    /** The file position for next read or write. */
    int64_t _filepos;
    /** True if the file should be read using direct IO */
    bool _directIOEnabled;

    char * buf() { return static_cast<char *>(_buf.get()); }
    const char * buf() const { return static_cast<const char *>(_buf.get()); }
protected:
    /** The file instance used for low-level file access. */
    std::unique_ptr<FastOS_FileInterface> _file;

public:
    /**
     * Create buffered file.
     * @param file file instance that should be used for low-level
     *             file access. If this is NULL, an instance of
     *             FastOS_File will be created. NOTE: the file
     *             instance given here will be deleted by
     *             the destructor.
     **/
    Fast_BufferedFile(FastOS_FileInterface *file, size_t bufferSize);
    Fast_BufferedFile(FastOS_FileInterface *file);
    Fast_BufferedFile();
    Fast_BufferedFile(size_t bufferSize);
    Fast_BufferedFile(const Fast_BufferedFile &) = delete;
    Fast_BufferedFile & operator = (const Fast_BufferedFile &) = delete;

    /**
     * Delete the file instance used for low-level file access.
     **/
    virtual ~Fast_BufferedFile();
    /**
     * Open an existing file for reading.
     *
     * @param name The name of the file to open.
     */
    void ReadOpenExisting(const char *name);
    /**
     * Open a file for reading.
     *
     * @param name The name of the file to open.
     */
    void ReadOpen(const char *name);

    /**
     * Open file for writing.
     *
     * @param name The name of the file to open.
     */
    void WriteOpen(const char *name);
    /**
     * Reset the internal start and end pointers to the
     * head of the buffer, thus "emptying" it.
     */
    void ResetBuf();
    /**
     * Write the buffer to the file. Caution: Uses obsolete
     * FastOS_FileInterface::WriteBuf.
     * Allocates a 32kB buffer if not previously allocated.
     */
    void flushWriteBuf();
    /**
     * Read from the file into the buffer. Allocates a 32kB
     * buffer if not previously allocated. Fills the buffer,
     * or reads as much as possible if the (rest of) the file
     * is smaller than the buffer.
     * Caution: If the amount read is smaller than the expected
     * amount, the method will abort.
     */
    void fillReadBuf();
    /**
     * Read the next line of the buffered file into a buffer,
     * reading from the file as necessary.
     *
     * @param buf The buffer to fill.
     * @param buflen The size of the buffer.
     * @return Pointer to the start of the next line, of NULL if no line.
     */
    char * ReadLine(char *buf, size_t buflen);
    /**
     * Write a buffer to a buffered file, flushing to file
     * as necessary.
     *
     * @param src The source buffer.
     * @param srclen The length of the source buffer.
     */
    [[nodiscard]] ssize_t Write2(const void*, size_t) override;
    /**
     * Write a string to a buffered file, flushing to file
     * as necessary.
     *
     * @param src The source string.
     */
    void WriteString(const char *src);
    /**
     * Read from the buffered file into a buffer, reading from
     * the file as necessary.
     *
     * @param dst The destination buffer.
     * @param dstlen The length of the destination buffer.
     * @return The number of bytes read.
     */
    [[nodiscard]] ssize_t Read(void *dst, size_t dstlen) override;
    /**
     * Write one byte to the buffered file, flushing to
     * file if necessary.
     *
     * @param byte The byte to write.
     */
    void WriteByte(char byte);

    /**
     * Add an unsigned int number as ASCII text in base 10 to the buffered
     * file using a fixed width with a designated fill character.
     *
     * @param num The number to add.
     * @param fieldw The number of characters to use.
     * @param fill The character to left-pad the field with,
     *     for instance '0' or ' '.
     */
    void addNum(unsigned int num, int fieldw, char fill);

    /**
     * Test for end of file.
     *
     * @return bool True if all bytes have been read from the
     *    buffered file.
     */
    bool Eof() const;
    /**
     * Get the size of the file.
     *
     * @return int64_t The size of the file.
     */
    int64_t getSize () const override;
    /**
     * Truncate or extend the file to a new size. Required write
     * access.
     *
     * @return bool True if successful.
     */
    bool SetSize (int64_t s) override;
    /**
     * Test if the file is opened.
     *
     * @return bool True if the file is currently opened.
     */
    bool IsOpened () const override;
    /**
     * Force completion of pending disk writes (flush cache).
     */
    [[nodiscard]] bool Sync() override;

    /**
     * Turn on direct IO.
     */
    void EnableDirectIO() override;
    void EnableSyncWrites() override;

    /**
     * Flush the buffer. If in write mode, write the buffer to
     * the file, then reset the buffer.
     */
    void Flush();
    /**
     * Flush the buffer, and close the file instance.
     * @return The result of the Close operation.
     */
    [[nodiscard]] bool Close () override;
    /**
     * Get the buffered file position, in bytes.
     * This takes into account the data in the buffer, that has
     * been read, or not written to the file.
     *
     * @return int64_t The file position.
     */
    int64_t getPosition () const override;
    /**
     * Set the position in the file. The next read or write
     * will continue from this position.
     *
     * @param s The position.
     * @return bool True if successful.
     */
    bool SetPosition(int64_t s) override;

    /**
     * Get name of buffered file.
     *
     * @return name of buffered file, or NULL if no file.
     */
    const char *GetFileName() const override;

    /**
     * Just forwarded to the real file to support FastOS_FileInterface.
     */
    bool Open(unsigned int, const char*) override;

    void alignEndForDirectIO();
};