File: request.h

package info (click to toggle)
megacmd 2.5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 32,592 kB
  • sloc: cpp: 326,437; ansic: 34,524; python: 4,630; java: 3,965; sh: 2,869; objc: 2,459; makefile: 197; xml: 113
file content (159 lines) | stat: -rw-r--r-- 5,372 bytes parent folder | download
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
/**
 * @file mega/request.h
 * @brief Generic request interface
 *
 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#ifndef MEGA_REQUEST_H
#define MEGA_REQUEST_H 1

#include "json.h"
#include "types.h"

#include <mega/common/badge_forward.h>

namespace mega {

// API request
class MEGA_API Request
{
private:
    vector<unique_ptr<Command>> cmds;
    string jsonresponse;
    JSON json;
    size_t processindex = 0;
    JSONSplitter mJsonSplitter;
    size_t mChunkedProgress = 0;

    // once we send the commands, any retry must be for exactly
    // the same JSON, or idempotence will not work properly
    mutable string cachedJSON;
    mutable string cachedIdempotenceId;
    mutable string cachedCounts;

public:
    void add(Command*);

    size_t size() const;

    string get(MegaClient* client, char reqidCounter[10], string& idempotenceId) const;

    void serverresponse(string&& movestring, MegaClient*);
    void servererror(const std::string &e, MegaClient* client);

    void process(MegaClient* client);
    bool processCmdJSON(Command* cmd, bool couldBeError, JSON& jsonResponse);
    bool processSeqTag(Command* cmd, bool withJSON, bool& parsedOk, bool inSeqTagArray, JSON& processingJson);

    m_off_t processChunk(const char* chunk, MegaClient*);
    m_off_t totalChunkedProgress();

    void clear();
    bool empty() const;
    void swap(Request&);
    bool stopProcessing = false;

    // if contains only one command and that command is FetchNodes
    bool isFetchNodes() const;

    Command* getCurrentCommand();
};


class MEGA_API RequestDispatcher
{
    // these ones have been sent to the server, but we haven't received the response yet
    Request inflightreq;
    retryreason_t inflightFailReason = RETRY_NONE;

    // client-server request double-buffering, in batches of up to MAX_COMMANDS
    deque<Request> nextreqs;

    // flags for dealing with resetting everything from a command in progress
    bool processing = false;
    bool clearWhenSafe = false;

    static const int MAX_COMMANDS = 10000;

    // unique request ID
    char reqid[10];

public:
    RequestDispatcher(PrnGen&);

    // Queue a command to be send to MEGA. Some commands must go in their own batch (in case other commands fail the whole batch), determined by the Command's `batchSeparately` field.
    void add(common::Badge<MegaClient> badge, Command*);

    // Commands are waiting and could be sent (could be a retry if connection failed etc) (they are not already sent, not awaiting response)
    bool readyToSend() const;

    // True if we started sending a Request and haven't received a server response yet,
    // and stays true even through network errors, retries, etc until we get that response
    bool cmdsInflight() const;

    // True if there is a request that has failed and needs retry because the API returned
    // an error: -3 or -4
    bool retryReasonIsApi() const;

    Command* getCurrentCommand(bool currSeqtagSeen);

    /**
     * @brief get the set of commands to be sent to the server (could be a retry)
     * @param includesFetchingNodes set to whether the commands include fetch nodes
     */
    string serverrequest(bool& includesFetchingNodes, MegaClient* client, string& idempotenceId);

    // Once we get a successful reply from the server, call this to complete everything
    // Since we need to support idempotence, we cannot add anything more to the in-progress request
    void serverresponse(string&& movestring, MegaClient*);

    // Call this function when a chunk of data is received from the server for chunked requests
    // The return value is the number of bytes that must be discarded. The chunk in the next call
    // must start with the data that was not discarded in the previous call
    size_t serverChunk(const char *chunk, MegaClient*);

    // Amount of data consumed for chunked requests, 0 for non-chunked requests
    size_t chunkedProgress();

    // If we need to retry (eg due to networking issue, abandoned req, server refusal etc) call this and we will abandon that attempt.
    // The req will be retried via the next serverrequest(), and idempotence takes care of avoiding duplicate actions
    void inflightFailure(retryreason_t reason);

    // If the server itself reports failure, use this one to resolve (commands are all failed)
    // and we will move to the next Request
    void servererror(const std::string &e, MegaClient*);

    void continueProcessing(MegaClient* client);

    void clear();

#if defined(MEGA_MEASURE_CODE) || defined(DEBUG)
    Request deferredRequests;
    std::function<bool(Command*)> deferRequests;
    void sendDeferred();
#endif
#ifdef MEGA_MEASURE_CODE
    uint64_t csRequestsSent = 0, csRequestsCompleted = 0;
    uint64_t csBatchesSent = 0, csBatchesReceived = 0;
#endif

};

} // namespace

#endif