aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-uws/examples/helpers/AsyncFileReader.h
blob: c086c1e953d96eb448e3e5dd66b13099ab5a04ea (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
#include <map>
#include <cstring>
#include <fstream>
#include <sstream>
#include <iostream>
#include <future>

/* This is just a very simple and inefficient demo of async responses,
 * please do roll your own variant or use a database or Node.js's async
 * features instead of this really bad demo */
struct AsyncFileReader {
private:
    /* The cache we have in memory for this file */
    std::string cache;
    int cacheOffset;
    bool hasCache;

    /* The pending async file read (yes we only support one pending read) */
    std::function<void(std::string_view)> pendingReadCb;

    int fileSize;
    std::string fileName;
    std::ifstream fin;
    uWS::Loop *loop;

public:
    /* Construct a demo async. file reader for fileName */
    AsyncFileReader(std::string fileName) : fileName(fileName) {
        fin.open(fileName, std::ios::binary);

        // get fileSize
        fin.seekg(0, fin.end);
        fileSize = fin.tellg();

        //std::cout << "File size is: " << fileSize << std::endl;

        // cache up 1 mb!
        cache.resize(1024 * 1024);

        //std::cout << "Caching 1 MB at offset = " << 0 << std::endl;
        fin.seekg(0, fin.beg);
        fin.read(cache.data(), cache.length());
        cacheOffset = 0;
        hasCache = true;

        // get loop for thread

        loop = uWS::Loop::get();
    }

    /* Returns any data already cached for this offset */
    std::string_view peek(int offset) {
        /* Did we hit the cache? */
        if (hasCache && offset >= cacheOffset && ((offset - cacheOffset) < cache.length())) {
            /* Cache hit */
            //std::cout << "Cache hit!" << std::endl;

            /*if (fileSize - offset < cache.length()) {
                std::cout << "LESS THAN WHAT WE HAVE!" << std::endl;
            }*/

            int chunkSize = std::min<int>(fileSize - offset, cache.length() - offset + cacheOffset);

            return std::string_view(cache.data() + offset - cacheOffset, chunkSize);
        } else {
            /* Cache miss */
            //std::cout << "Cache miss!" << std::endl;
            return std::string_view(nullptr, 0);
        }
    }

    /* Asynchronously request more data at offset */
    void request(int offset, std::function<void(std::string_view)> cb) {

        // in this case, what do we do?
        // we need to queue up this chunk request and callback!
        // if queue is full, either block or close the connection via abort!
        if (!hasCache) {
            // already requesting a chunk!
            std::cout << "ERROR: already requesting a chunk!" << std::endl;
            return;
        }

        // disable cache
        hasCache = false;

        std::async(std::launch::async, [this, cb, offset]() {
            //std::cout << "ASYNC Caching 1 MB at offset = " << offset << std::endl;



            // den har stängts! öppna igen!
            if (!fin.good()) {
                fin.close();
                //std::cout << "Reopening fin!" << std::endl;
                fin.open(fileName, std::ios::binary);
            }
            fin.seekg(offset, fin.beg);
            fin.read(cache.data(), cache.length());

            cacheOffset = offset;

            loop->defer([this, cb, offset]() {

                int chunkSize = std::min<int>(cache.length(), fileSize - offset);

                // båda dessa sker, wtf?
                if (chunkSize == 0) {
                    std::cout << "Zero size!?" << std::endl;
                }

                if (chunkSize != cache.length()) {
                    std::cout << "LESS THAN A CACHE 1 MB!" << std::endl;
                }

                hasCache = true;
                cb(std::string_view(cache.data(), chunkSize));
            });
        });
    }

    /* Abort any pending async. request */
    void abort() {

    }

    int getFileSize() {
        return fileSize;
    }
};
25 16:19:44 +0000'>2022-02-25[ci] yarn formatGravatar FredKSchott 1-7/+6 2022-02-25Add Non-HTML Pages example (#2637)Gravatar Joel Kuzmarski 11-0/+136 2022-02-25[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-24[ci] yarn formatGravatar natemoo-re 2-24/+24 2022-02-24[ci] release (#2641)astro@0.23.1@astrojs/markdown-remark@0.6.2Gravatar github-actions[bot] 38-90/+81 2022-02-24ensure utf8 encoding when serving html (#2654)Gravatar Fred K. Schott 3-4/+9 2022-02-24fix(core): Issue #2625. error with process.env.LANG larger than 5 (#2645)Gravatar Javier Cortés 2-1/+6 2022-02-24[ci] update lockfile (#2646)Gravatar Fred K. Schott 1-130/+124 2022-02-24chore: upgrade compiler (#2653)Gravatar Nate Moore 3-11/+11 2022-02-24[ci] yarn formatGravatar natemoo-re 2-5/+5 2022-02-24Add fine-grained HMR support (#2649)Gravatar Nate Moore 7-36/+37 2022-02-24[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-23Fixed incorrect types and imports (#2630)Gravatar Juan Martín Seery 27-35/+37 2022-02-23Add sass dev dep to blog-multiple-authors example (#2643)Gravatar Joel Kuzmarski 1-1/+2 2022-02-23Fix(component): align starting position in Markdown slot (#2631)Gravatar Shinobu Hayashi 4-6/+61 2022-02-23[ci] yarn formatGravatar matthewp 1-1/+1 2022-02-23Run all smoke tests with the static build (#2609)Gravatar Matthew Phillips 2-26/+32 2022-02-23[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-22[ci] update lockfile (#2624)Gravatar Fred K. Schott 1-171/+201 2022-02-22Fixed shiki import to work with "type": "module" (#2628)Gravatar Juan Martín Seery 3-5/+13