Ejemplo n.º 1
0
void	HLDirectory::GetItem(UInt32 inIndex, FSRef& outFSRef)
{
	FetchItems();
	
	ItemList::iterator theIterator = mItems->begin();
	std::advance(theIterator, inIndex);
	
	ThrowIf(theIterator == mItems->end(), CAException(paramErr), "HLDirectory::GetItem: index out of range");
	
	memcpy(&outFSRef, &(*theIterator), sizeof(FSRef));
}
Ejemplo n.º 2
0
 lldb::SBQueueItem
 GetPendingItemAtIndex (uint32_t idx)
 {
     SBQueueItem result;
     FetchItems();
     if (m_pending_items_fetched && idx < m_pending_items.size())
     {
         result.SetQueueItem (m_pending_items[idx]);
     }
     return result;
 }
Ejemplo n.º 3
0
 uint32_t
 GetNumItems ()
 {
     uint32_t result = 0;
     FetchItems();
 
     if (m_queue_items_fetched)
     {
         result = m_items.size();
     }
     return result;
 }
Ejemplo n.º 4
0
void ItemsManagerWorker::OnFirstTabReceived() {
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(QObject::sender());
    QByteArray bytes = reply->readAll();
    rapidjson::Document doc;
    doc.Parse(bytes.constData());

    int index = 0;
    if (!doc.IsObject()) {
        QLOG_ERROR() << "Can't even fetch first tab. Failed to update items.";
        updating_ = false;
        return;
    }
    if (!doc.HasMember("tabs") || doc["tabs"].Size() == 0) {
        QLOG_WARN() << "There are no tabs, this should not happen, bailing out.";
        updating_ = false;
        return;
    }

    tabs_as_string_ = Util::RapidjsonSerialize(doc["tabs"]);

    QLOG_DEBUG() << "Received tabs list, there are" << doc["tabs"].Size() << "tabs";
    tabs_.clear();
    for (auto &tab : doc["tabs"]) {
        std::string label = tab["n"].GetString();
        tabs_.push_back(label);
        if (index > 0) {
            ItemLocation location;
            location.set_type(ItemLocationType::STASH);
            location.set_tab_id(index);
            location.set_tab_label(label);
            if (!tab.HasMember("hidden") || !tab["hidden"].GetBool())
                QueueRequest(MakeTabRequest(index), location);
        }
        ++index;
    }

    ItemLocation first_tab_location;
    first_tab_location.set_type(ItemLocationType::STASH);
    first_tab_location.set_tab_id(0);
    first_tab_location.set_tab_label(tabs_[0]);
    if (!doc["tabs"][0].HasMember("hidden") || !doc["tabs"][0]["hidden"].GetBool())
        ParseItems(&doc["items"], first_tab_location, doc.GetAllocator());

    total_needed_ = queue_.size() + 1;
    total_completed_ = 1;
    FetchItems(kThrottleRequests - 1);

    connect(signal_mapper_, SIGNAL(mapped(int)), this, SLOT(OnTabReceived(int)));
    reply->deleteLater();
}
Ejemplo n.º 5
0
void ItemsManagerWorker::OnFirstTabReceived() {
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(QObject::sender());
    QByteArray bytes = reply->readAll();
    rapidjson::Document doc;
    doc.Parse(bytes.constData());

    if (!doc.IsObject()) {
        QLOG_ERROR() << "Can't even fetch first tab. Failed to update items.";
        updating_ = false;
        return;
    }
    if (!doc.HasMember("tabs") || doc["tabs"].Size() == 0) {
        QLOG_WARN() << "There are no tabs, this should not happen, bailing out.";
        updating_ = false;
        return;
    }

    tabs_as_string_ = Util::RapidjsonSerialize(doc["tabs"]);

    QLOG_DEBUG() << "Received tabs list, there are" << doc["tabs"].Size() << "tabs";
    tabs_.clear();

    // Create tab location objects
    for (auto &tab : doc["tabs"]) {
        std::string label = tab["n"].GetString();
        auto index = tab["i"].GetInt();
        // Ignore hidden locations
        if (!doc["tabs"][index].HasMember("hidden") || !doc["tabs"][index]["hidden"].GetBool())
            tabs_.push_back(ItemLocation(index, label, ItemLocationType::STASH));
    }

    // Immediately parse items received from this tab (first_fetch_tab_) and Queue requests for the others
    for (auto const &tab: tabs_) {
        auto index = tab.get_tab_id();
        if (index == first_fetch_tab_) {
            ParseItems(&doc["items"], tab, doc.GetAllocator());
        } else {
            QueueRequest(MakeTabRequest(index, tab), tab);
        }
    }

    total_needed_ = queue_.size() + 1;
    total_completed_ = 1;
    total_cached_ = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool() ? 1:0;

    FetchItems(kThrottleRequests - 1);

    connect(signal_mapper_, SIGNAL(mapped(int)), this, SLOT(OnTabReceived(int)));
    reply->deleteLater();
}
Ejemplo n.º 6
0
void ItemsManagerWorker::OnTabReceived(int request_id) {
    if (!replies_.count(request_id)) {
        QLOG_WARN() << "Received a reply for request" << request_id << "that was not requested.";
        return;
    }

    ItemsReply reply = replies_[request_id];
    QLOG_INFO() << "Received a reply for" << reply.request.location.GetHeader().c_str();
    QByteArray bytes = reply.network_reply->readAll();
    rapidjson::Document doc;
    doc.Parse(bytes.constData());

    bool error = false;
    if (!doc.IsObject()) {
        QLOG_WARN() << request_id << "got a non-object response";
        error = true;
    } else if (doc.HasMember("error")) {
        // this can happen if user is browsing stash in background and we can't know about it
        QLOG_WARN() << request_id << "got 'error' instead of stash tab contents";
        error = true;
    }

    // re-queue a failed request
    if (error)
        QueueRequest(reply.request.network_request, reply.request.location);

    ++requests_completed_;

    if (!error)
        ++total_completed_;

    bool throttled = false;
    if (requests_completed_ == requests_needed_ && queue_.size() > 0) {
        throttled = true;
        QLOG_INFO() << "Sleeping one minute to prevent throttling.";
        QTimer::singleShot(kThrottleSleep * 1000, this, SLOT(FetchItems()));
    }
    CurrentStatusUpdate status = CurrentStatusUpdate();
    status.state = throttled ? ProgramState::ItemsPaused : ProgramState::ItemsReceive;
    status.progress = total_completed_;
    status.total = total_needed_;
    if (total_completed_ == total_needed_)
        status.state = ProgramState::ItemsCompleted;
    emit StatusUpdate(status);

    if (error)
        return;

    ParseItems(&doc["items"], reply.request.location, doc.GetAllocator());

    if (total_completed_ == total_needed_) {
        // all requests completed
        emit ItemsRefreshed(items_, tabs_, false);

        // since we build items_as_string_ in a hackish way inside ParseItems last character will either be
        // ' ' when no items were parsed or ',' when at least one item is parsed, and the first character is '['
        items_as_string_[items_as_string_.size() - 1] = ']';

        // DataManager is thread safe so it's ok to call it here
        data_manager_.Set("items", items_as_string_);
        data_manager_.Set("tabs", tabs_as_string_);

        updating_ = false;
        QLOG_INFO() << "Finished updating stash.";

        // if we're at the verge of getting throttled, sleep so we don't
        if (requests_completed_ == kThrottleRequests)
            QTimer::singleShot(kThrottleSleep, this, SLOT(PreserveSelectedCharacter()));
        else
            PreserveSelectedCharacter();
    }

    reply.network_reply->deleteLater();
}
Ejemplo n.º 7
0
void ItemsManagerWorker::OnFirstTabReceived() {
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(QObject::sender());
    QByteArray bytes = reply->readAll();
    rapidjson::Document doc;
    doc.Parse(bytes.constData());

    int index = 0;
    if (!doc.IsObject()) {
        QLOG_ERROR() << "Can't even fetch first tab. Failed to update items.";
        updating_ = false;
        StatusFinished();
        return;
    }
    if (!doc.HasMember("tabs") || doc["tabs"].Size() == 0) {
        QLOG_WARN() << "There are no tabs, this should not happen, bailing out.";
        updating_ = false;
        StatusFinished();
        return;
    }

    tabs_as_string_ = Util::RapidjsonSerialize(doc["tabs"]);

    QLOG_INFO() << "Received tabs list, there are" << doc["tabs"].Size() << "tabs";

    // Setup tab exclusions
    std::string exclusions = data_manager_.Get("tab_exclusions");
    QList<QRegularExpression> expressions;
    rapidjson::Document exclusionDoc;
    exclusionDoc.Parse(exclusions.c_str());

    if (exclusionDoc.IsArray()) {
        for (auto &excl : exclusionDoc) {
            QRegularExpression expr(excl.GetString());
            if (!expr.pattern().isEmpty() && expr.isValid()) expressions.append(expr);
        }
    }

    int tabsParsed = 0;
    tabs_.clear();
    for (auto &tab : doc["tabs"]) {
        std::string label = tab["n"].GetString();
        bool skip = false;
        for (QRegularExpression expr : expressions) {
            QRegularExpressionMatch match = expr.match(QString::fromStdString(label));
            if (match.isValid() && match.hasMatch()) {
                skip = true;
                break;
            }
        }

        if (!skip) {
            tabs_.push_back(label);
            ItemLocation location;
            location.set_type(ItemLocationType::STASH);
            location.set_tab_id(index);
            location.set_tab_label(label);

            if (index == 0) {
                // We already have this tab (it's the first one we get).
                // Parse the items now that we have them
                if (!doc["tabs"][0].HasMember("hidden") || !doc["tabs"][0]["hidden"].GetBool()) {
                    ParseItems(&doc["items"], location, doc.GetAllocator());
                    ++tabsParsed;
                }
            }
            else if (!tab.HasMember("hidden") || !tab["hidden"].GetBool()) {
                // If it's not hidden, then we need to download
                QueueRequest(MakeTabRequest(index), location);
            }
        }
        ++index;
    }

    if (tabs_.size() == 0) {
        QLOG_WARN() << "There are no tabs to be downloaded. Try clearing your tab exclusions list.";
        updating_ = false;
        StatusFinished();
        return;
    }

    // tabsParsed will be 1 if the first tab was included in the initial download
    total_needed_ = queue_.size() + tabsParsed;
    total_completed_ = tabsParsed;
    FetchItems(kThrottleRequests - tabsParsed);

    connect(signal_mapper_, SIGNAL(mapped(int)), this, SLOT(OnTabReceived(int)));
    reply->deleteLater();
}
Ejemplo n.º 8
0
UInt32	HLDirectory::GetNumberItems()
{
	FetchItems();
	return mItems->size();
}
Ejemplo n.º 9
0
void ItemsManagerWorker::OnFirstTabReceived() {
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(QObject::sender());
    QByteArray bytes = reply->readAll();
    rapidjson::Document doc;
    doc.Parse(bytes.constData());

    int index = 0;
    if (!doc.IsObject()) {
        QLOG_ERROR() << "Can't even fetch first tab. Failed to update items.";
        updating_ = false;
        return;
    }
    if (!doc.HasMember("tabs") || doc["tabs"].Size() == 0) {
        QLOG_WARN() << "There are no tabs, this should not happen, bailing out.";
        updating_ = false;
        return;
    }

    tabs_as_string_ = Util::RapidjsonSerialize(doc["tabs"]);

    QLOG_INFO() << "Received tabs list, there are" << doc["tabs"].Size() << "tabs";

    // Setup tab exclusions
    std::string exclusions = data_manager_.Get("tab_exclusions");
    QList<QRegularExpression> expressions;
    rapidjson::Document exclusionDoc;
    exclusionDoc.Parse(exclusions.c_str());

    if (exclusionDoc.IsArray()) {
        for (auto &excl  : exclusionDoc) {
            expressions.append(QRegularExpression(excl.GetString()));
        }
    }

    tabs_.clear();
    for (auto &tab : doc["tabs"]) {
        std::string label = tab["n"].GetString();
        bool skip = false;
        for (QRegularExpression expr : expressions) {
            QRegularExpressionMatch match = expr.match(QString::fromStdString(label));
            if (match.isValid() && match.hasMatch()) {
                skip = true;
                break;
            }
        }

        tabs_.push_back(label);
        if (index > 0 || skip) {
            ItemLocation location;
            location.set_type(ItemLocationType::STASH);
            location.set_tab_id(index);
            location.set_tab_label(label);
            if (!tab.HasMember("hidden") || !tab["hidden"].GetBool())
                QueueRequest(MakeTabRequest(skip ? 0 : index), location);
        }
        ++index;
    }

    ItemLocation first_tab_location;
    first_tab_location.set_type(ItemLocationType::STASH);
    first_tab_location.set_tab_id(0);
    first_tab_location.set_tab_label(tabs_[0]);
    if (!doc["tabs"][0].HasMember("hidden") || !doc["tabs"][0]["hidden"].GetBool())
        ParseItems(&doc["items"], first_tab_location, doc.GetAllocator());

    total_needed_ = queue_.size() + 1;
    total_completed_ = 1;
    FetchItems(kThrottleRequests - 1);

    connect(signal_mapper_, SIGNAL(mapped(int)), this, SLOT(OnTabReceived(int)));
    reply->deleteLater();
}
Ejemplo n.º 10
0
void ItemsManagerWorker::OnTabReceived(int request_id) {
    if (!replies_.count(request_id)) {
        QLOG_WARN() << "Received a reply for request" << request_id << "that was not requested.";
        return;
    }

    ItemsReply reply = replies_[request_id];

    bool cache_status = reply.network_reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool();

    if (cache_status) {
        QLOG_DEBUG() << "Received a cached reply for" << reply.request.location.GetHeader().c_str();
        ++cached_requests_completed_;
        ++total_cached_;
    } else {
        QLOG_DEBUG() << "Received a reply for" << reply.request.location.GetHeader().c_str();
    }

    QByteArray bytes = reply.network_reply->readAll();
    rapidjson::Document doc;
    doc.Parse(bytes.constData());

    bool error = false;
    if (!doc.IsObject()) {
        QLOG_WARN() << request_id << "got a non-object response";
        error = true;
    } else if (doc.HasMember("error")) {
        // this can happen if user is browsing stash in background and we can't know about it
        QLOG_WARN() << request_id << "got 'error' instead of stash tab contents";
        error = true;
    }

    // re-queue a failed request
    if (error) {
        // We can 'cache' error response document so make sure we remove it
        // before reque
        tab_cache_->remove(reply.request.network_request.url());
        QueueRequest(reply.request.network_request, reply.request.location);
    }

    ++requests_completed_;

    if (!error)
        ++total_completed_;

    bool throttled = false;
    if (requests_completed_ == requests_needed_ && queue_.size() > 0) {
        if (cached_requests_completed_ > 0) {
            // We basically don't want cached requests to count against throttle limit
            // so if we did get any cached requests fetch up to that number without a
            // large delay
            QTimer::singleShot(1, [&]() {
                FetchItems(cached_requests_completed_);
            });
        } else {
            throttled = true;
            QLOG_DEBUG() << "Sleeping one minute to prevent throttling.";
            QTimer::singleShot(kThrottleSleep * 1000, this, SLOT(FetchItems()));
        }
    }
    CurrentStatusUpdate status = CurrentStatusUpdate();
    status.state = throttled ? ProgramState::ItemsPaused : ProgramState::ItemsReceive;
    status.progress = total_completed_;
    status.total = total_needed_;
    status.cached = total_cached_;
    if (total_completed_ == total_needed_)
        status.state = ProgramState::ItemsCompleted;
    emit StatusUpdate(status);

    if (error)
        return;

    ParseItems(&doc["items"], reply.request.location, doc.GetAllocator());

    if (total_completed_ == total_needed_) {
        // It's possible that we receive character vs stash tabs out of order, or users
        // move items around in a tab and we get them in a different order. For
        // consistency we want to present the tab data in a deterministic way to the rest
        // of the application.  Especially so we don't try to update shop when nothing actually
        // changed.  So sort items_ here before emitting and then generate
        // item list as strings.

        std::sort(begin(items_), end(items_), [](const std::shared_ptr<Item> &a, const std::shared_ptr<Item> &b) {
            return b->location() < a->location();
        });

        QStringList tmp;
        for (auto const &item: items_) {
            tmp.push_back(item->json().c_str());
        }
        auto items_as_string = std::string("[") + tmp.join(",").toStdString() + "]";

        // all requests completed
        emit ItemsRefreshed(items_, tabs_, false);

        // DataStore is thread safe so it's ok to call it here
        data_.Set("items", items_as_string);
        data_.Set("tabs", tabs_as_string_);

        updating_ = false;
        QLOG_DEBUG() << "Finished updating stash.";

        // if we're at the verge of getting throttled, sleep so we don't
        if (requests_completed_ == kThrottleRequests)
            QTimer::singleShot(kThrottleSleep, this, SLOT(PreserveSelectedCharacter()));
        else
            PreserveSelectedCharacter();
    }

    reply.network_reply->deleteLater();
}