diff options
Diffstat (limited to 'src/imports/jsondb/jsondbcachinglistmodel.cpp')
-rw-r--r-- | src/imports/jsondb/jsondbcachinglistmodel.cpp | 589 |
1 files changed, 372 insertions, 217 deletions
diff --git a/src/imports/jsondb/jsondbcachinglistmodel.cpp b/src/imports/jsondb/jsondbcachinglistmodel.cpp index c34617c7..afcec554 100644 --- a/src/imports/jsondb/jsondbcachinglistmodel.cpp +++ b/src/imports/jsondb/jsondbcachinglistmodel.cpp @@ -40,15 +40,18 @@ ****************************************************************************/ //#define JSONDB_LISTMODEL_DEBUG +//#define JSONDB_LISTMODEL_BENCHMARK #include "jsondbcachinglistmodel.h" #include "jsondbcachinglistmodel_p.h" -#include "private/jsondb-strings_p.h" #include "plugin.h" #include <QJSEngine> #include <QJSValueIterator> #include <QDebug> +#ifdef JSONDB_LISTMODEL_BENCHMARK +#include <QElapsedTimer> +#endif /*! \internal @@ -70,13 +73,6 @@ JsonDbCachingListModelPrivate::JsonDbCachingListModelPrivate(JsonDbCachingListMo void JsonDbCachingListModelPrivate::init() { - Q_Q(JsonDbCachingListModel); - q->connect(&dbClient, SIGNAL(response(int,const QVariant&)), - q, SLOT(_q_jsonDbResponse(int,const QVariant&)), - Qt::QueuedConnection); - q->connect(&dbClient, SIGNAL(error(int,int,const QString&)), - q, SLOT(_q_jsonDbErrorResponse(int,int,const QString&)), - Qt::QueuedConnection); } void JsonDbCachingListModelPrivate::setCacheParams(int maxItems) @@ -84,18 +80,29 @@ void JsonDbCachingListModelPrivate::setCacheParams(int maxItems) objectCache.setPageSize(maxItems); chunkSize = objectCache.chunkSize(); lowWaterMark = objectCache.chunkSize()/4; - //lowWaterMark = objectCache.pageSize/4; } JsonDbCachingListModelPrivate::~JsonDbCachingListModelPrivate() { - // Why do we need to do this while destroying the object clearNotifications(); + while (!keyRequests.isEmpty()) { + delete keyRequests[0]; + keyRequests.removeFirst(); + } + while (!indexRequests.isEmpty()) { + delete indexRequests[0]; + indexRequests.removeFirst(); + } + while (!valueRequests.isEmpty()) { + delete valueRequests[0]; + valueRequests.removeFirst(); + } + } // insert item notification handler // + add items, for chunked read -void JsonDbCachingListModelPrivate::addItem(const QVariantMap &item, int partitionIndex) +void JsonDbCachingListModelPrivate::addItem(const QJsonObject &item, int partitionIndex) { Q_Q(JsonDbCachingListModel); const QString &uuid = item.value(QLatin1String("_uuid")).toString(); @@ -103,7 +110,10 @@ void JsonDbCachingListModelPrivate::addItem(const QVariantMap &item, int partiti if (objectSortValues.contains(uuid)) return; - SortingKey key(partitionIndex, item, ascendingOrders, orderPaths, partitionIndexDetails[0].spec); + QVariantList vl; + vl.append(uuid); + vl.append(item.value(QLatin1String("_indexValue")).toVariant()); + SortingKey key(partitionIndex, vl, QList<bool>() << ascendingOrder, partitionIndexDetails[partitionIndex].spec); QMap<SortingKey, QString>::const_iterator begin = objectUuids.constBegin(); QMap<SortingKey, QString>::const_iterator end = objectUuids.constEnd(); QMap<SortingKey, QString>::const_iterator i = objectUuids.upperBound(key); @@ -120,7 +130,7 @@ void JsonDbCachingListModelPrivate::addItem(const QVariantMap &item, int partiti // deleteitem notification handler -void JsonDbCachingListModelPrivate::deleteItem(const QVariantMap &item, int partitionIndex) +void JsonDbCachingListModelPrivate::deleteItem(const QJsonObject &item, int partitionIndex) { Q_Q(JsonDbCachingListModel); QString uuid = item.value(QLatin1String("_uuid")).toString(); @@ -144,14 +154,17 @@ void JsonDbCachingListModelPrivate::deleteItem(const QVariantMap &item, int part } // updateitem notification handler -void JsonDbCachingListModelPrivate::updateItem(const QVariantMap &item, int partitionIndex) +void JsonDbCachingListModelPrivate::updateItem(const QJsonObject &item, int partitionIndex) { Q_Q(JsonDbCachingListModel); QString uuid = item.value(QLatin1String("_uuid")).toString(); QMap<QString, SortingKey>::const_iterator keyIndex = objectSortValues.constFind(uuid); if (keyIndex != objectSortValues.constEnd()) { SortingKey key = keyIndex.value(); - SortingKey newKey(partitionIndex, item, ascendingOrders, orderPaths, partitionIndexDetails[0].spec); + QVariantList vl; + vl.append(uuid); + vl.append(item.value(QLatin1String("_indexValue")).toVariant()); + SortingKey newKey(partitionIndex, vl, QList<bool>() << ascendingOrder, partitionIndexDetails[partitionIndex].spec); QMap<SortingKey, QString>::const_iterator begin = objectUuids.constBegin(); QMap<SortingKey, QString>::const_iterator end = objectUuids.constEnd(); QMap<SortingKey, QString>::const_iterator oldPos = objectUuids.constFind(key); @@ -276,55 +289,50 @@ void JsonDbCachingListModelPrivate::createObjectRequests(int startIndex, int max r.lastOffset = indexNSizes[i].index; r.lastSize = -1; r.requestCount = indexNSizes[i].count; - r.requestId = dbClient.query(query+sortOrder, indexNSizes[i].index, - qMin(r.requestCount, chunkSize), - partitionObjects[i]->name()); + QJsonDbReadRequest *request = valueRequests[i]->newRequest(i); + request->setQuery(query+sortOrder); + request->setProperty("queryOffset", indexNSizes[i].index); + request->setQueryLimit(qMin(r.requestCount, chunkSize)); + request->setPartition(partitionObjects[i]->name()); + JsonDatabase::sharedConnection().send(request); #ifdef JSONDB_LISTMODEL_DEBUG qDebug()<<"Query"<<query+sortOrder<<partitionObjects[i]->name(); - qDebug()<<"Request "<<r.requestId << + qDebug()<<"Request "<<request->property("requestId") << "Total Count "<<r.requestCount << "Offset"<<r.lastOffset<< "Count "<<qMin(r.requestCount,chunkSize); #endif } else { - r.requestId = -1; r.lastSize = 0; r.requestCount = 0; } } - delete indexNSizes; + delete [] indexNSizes; } -void JsonDbCachingListModelPrivate::verifyIndexSpec(const QVariant &v, int partitionIndex) +void JsonDbCachingListModelPrivate::verifyIndexSpec(const QList<QJsonObject> &items, int partitionIndex) { Q_Q(JsonDbCachingListModel); - QVariantMap m = v.toMap(); - QVariantList items; - if (m.contains(QLatin1String("data"))) - items = m.value(QLatin1String("data")).toList(); SortIndexSpec &indexSpec = partitionIndexDetails[partitionIndex].spec; - QString propertyFunction; - QString indexName; bool validIndex = false; - if (orderProperties.count()) - indexName = orderProperties[0]; if (items.count()) { - QVariantMap spec = items[0].toMap(); - indexSpec.propertyName = spec.value(QLatin1String("propertyName")).toString(); - indexSpec.propertyType = spec.value(QLatin1String("propertyType")).toString(); + QJsonObject spec = items[0]; + indexSpec.propertyName = QLatin1String("_indexValue"); + QString propertyType = spec.value(QLatin1String("propertyType")).toString(); indexSpec.name = spec.value(QLatin1String("name")).toString(); - propertyFunction = spec.value(QLatin1String("propertyFunction")).toString(); + indexSpec.caseSensitive = true; if (!indexName.isEmpty()) { if (indexSpec.name == indexName) { - validIndex = true; - if (!indexSpec.propertyType.compare(QLatin1String("string"), Qt::CaseInsensitive)) { + if (!propertyType.compare(QLatin1String("string"), Qt::CaseInsensitive)) { indexSpec.type = SortIndexSpec::String; - indexSpec.caseSensitive = true; + validIndex = true; + } else if (!propertyType.compare(QLatin1String("number"), Qt::CaseInsensitive)) { + indexSpec.type = SortIndexSpec::Number; + validIndex = true; + } else if (!propertyType.compare(QLatin1String("UUID"), Qt::CaseInsensitive)) { + indexSpec.type = SortIndexSpec::UUID; + validIndex = true; } - if (indexSpec.propertyName.isEmpty()) - validIndex = false; - if (!propertyFunction.isEmpty()) - validIndex = false; // Cannot support property functions } } } @@ -345,7 +353,6 @@ void JsonDbCachingListModelPrivate::verifyIndexSpec(const QVariant &v, int parti } if (checkedAll) { //Start fetching the keys. - orderProperties[0] = indexSpec.propertyName; setQueryForSortKeys(); for (int i = 0; i < partitionKeyRequestDetails.count(); i++) { fetchPartitionKeys(i); @@ -354,32 +361,17 @@ void JsonDbCachingListModelPrivate::verifyIndexSpec(const QVariant &v, int parti } } -void JsonDbCachingListModelPrivate::fillKeys(const QVariant &v, int partitionIndex) +void JsonDbCachingListModelPrivate::fillKeys(const QList<QJsonObject> &items, int partitionIndex) { - Q_Q(JsonDbCachingListModel); - QVariantMap m = v.toMap(); - QVariantList items; - if (m.contains(QLatin1String("data"))) - items = m.value(QLatin1String("data")).toList(); - // Check if the sort key is same as requested. - // We can only support this model if an index is present - if (m.contains(QLatin1String("sortKeys"))) { - const QVariantList &sortKeys = m.value(QLatin1String("sortKeys")).toList(); - if (!(sortKeys.count() && sortKeys[0].toString() == orderProperties[0])) { - qWarning() << "Error JsonDbCachingListModel requires Index for "<<orderProperties[0]<<" Sort Keys"<<sortKeys; - reset(); - state = JsonDbCachingListModel::Error; - emit q->stateChanged(state); - return; - } - } RequestInfo &r = partitionKeyRequestDetails[partitionIndex]; r.lastSize = items.size(); for (int i = 0; i < r.lastSize; i++) { - const QVariantList &item = items.at(i).toList(); - const QString &uuid = item.at(0).toString(); - - SortingKey key(partitionIndex, item, ascendingOrders, partitionIndexDetails[0].spec); + const QJsonObject &item = items.at(i); + const QString &uuid = item.value(QLatin1String("_uuid")).toString(); + QVariantList vl; + vl.append(uuid); + vl.append(item.value(QLatin1String("_indexValue")).toVariant()); + SortingKey key(partitionIndex, vl, QList<bool>() << ascendingOrder, partitionIndexDetails[partitionIndex].spec); objectUuids.insert(key, uuid); partitionObjectUuids[partitionIndex].insert(key, uuid); objectSortValues.insert(uuid, key); @@ -389,7 +381,7 @@ void JsonDbCachingListModelPrivate::fillKeys(const QVariant &v, int partitionInd // all the results bool allRequestsFinished = true; for (int i = 0; i < partitionKeyRequestDetails.count(); i++) { - if (partitionKeyRequestDetails[i].lastSize >= chunkSize*2 || partitionKeyRequestDetails[i].lastSize == -1) { + if (partitionKeyRequestDetails[i].lastSize >= chunkSize || partitionKeyRequestDetails[i].lastSize == -1) { allRequestsFinished = false; break; } @@ -401,12 +393,12 @@ void JsonDbCachingListModelPrivate::fillKeys(const QVariant &v, int partitionInd #endif if (!objectUuids.count()) { for (int i = 0; i<partitionObjectDetails.count(); i++) { - fillData(QVariant(), i); + fillData(QList<QJsonObject>(), i); } return; } createObjectRequests(0, qMin(objectCache.maxItems(), objectUuids.count())); - } else if (r.lastSize >= chunkSize*2){ + } else if (r.lastSize >= chunkSize){ // more items, fetch next chunk of keys fetchNextKeyChunk(partitionIndex); } @@ -420,20 +412,16 @@ void JsonDbCachingListModelPrivate::emitDataChanged(int from, int to) emit q->dataChanged(modelIndexFrom, modelIndexTo); } -void JsonDbCachingListModelPrivate::fillData(const QVariant &v, int partitionIndex) +void JsonDbCachingListModelPrivate::fillData(const QList<QJsonObject> &items, int partitionIndex) { Q_Q(JsonDbCachingListModel); - QVariantMap m = v.toMap(); - QVariantList items; - if (m.contains(QLatin1String("data"))) - items = m.value(QLatin1String("data")).toList(); RequestInfo &r = partitionObjectDetails[partitionIndex]; r.lastSize = items.size(); r.requestCount -= r.lastSize; r.lastOffset += r.lastSize; for (int i = 0; i < r.lastSize; i++) { - const QVariantMap &item = items.at(i).toMap(); + const QJsonObject &item = items.at(i); const QString &uuid = item.value(QLatin1String("_uuid")).toString(); tmpObjects.insert(uuid, item); } @@ -499,11 +487,11 @@ void JsonDbCachingListModelPrivate::fillData(const QVariant &v, int partitionInd // retrieved all elements state = JsonDbCachingListModel::Ready; emit q->stateChanged(state); - for (int i = 0; i < pendingNotifications.size(); i++) { - const NotifyItem &pending = pendingNotifications[i]; - sendNotifications(pending.notifyUuid, pendingNotifications[i].item, pendingNotifications[i].action); + if (!pendingNotifications.isEmpty()) { + foreach (NotificationItem pending, pendingNotifications) + sendNotification(pending.partitionIndex, pending.item, pending.action); + pendingNotifications.clear(); } - pendingNotifications.clear(); if (requestQueue.count()) { QPair<int, int> req = requestQueue.takeFirst(); createObjectRequests(req.first, req.second); @@ -550,10 +538,7 @@ void JsonDbCachingListModelPrivate::reset() bool JsonDbCachingListModelPrivate::checkForDefaultIndexTypes(int index) { Q_Q(JsonDbCachingListModel); - if (!orderProperties.count()) - return false; bool defaultType = false; - QString indexName = orderProperties[0]; if (!indexName.compare(QLatin1String("_uuid")) || !indexName.compare(QLatin1String("_type"))) { defaultType = true; QMetaObject::invokeMethod(q, "_q_verifyDefaultIndexType", Qt::QueuedConnection, @@ -574,10 +559,12 @@ void JsonDbCachingListModelPrivate::fetchIndexSpec(int index) state = JsonDbCachingListModel::Querying; emit q->stateChanged(state); } - IndexInfo &r = partitionIndexDetails[index]; QPointer<JsonDbPartition> p = partitionObjects[index]; if (p) { - r.requestId = dbClient.query(queryForIndexSpec, 0, -1, p->name()); + QJsonDbReadRequest *request = indexRequests[index]->newRequest(index); + request->setQuery(queryForIndexSpec); + request->setPartition(p->name()); + JsonDatabase::sharedConnection().send(request); } } @@ -596,7 +583,11 @@ void JsonDbCachingListModelPrivate::fetchPartitionKeys(int index) if (p) { r.lastSize = -1; r.lastOffset = 0; - r.requestId = dbClient.query(queryForSortKeys, 0, chunkSize*2, p->name()); + QJsonDbReadRequest *request = keyRequests[index]->newRequest(index); + request->setQuery(queryForSortKeys); + request->setQueryLimit(chunkSize); + request->setPartition(p->name()); + JsonDatabase::sharedConnection().send(request); } } @@ -610,6 +601,9 @@ void JsonDbCachingListModelPrivate::initializeModel(bool reset) for (int i = 0; i < partitionObjectUuids.count(); i++) { partitionObjectUuids[i].clear(); } + for (int i = 0; i < partitionIndexDetails.count(); i++) { + partitionIndexDetails[i].clear(); + } } for (int i = 0; i < partitionObjects.count(); i++) { fetchIndexSpec(i); @@ -625,17 +619,26 @@ void JsonDbCachingListModelPrivate::fetchModel(bool reset) void JsonDbCachingListModelPrivate::fetchNextKeyChunk(int partitionIndex) { RequestInfo &r = partitionKeyRequestDetails[partitionIndex]; - r.lastOffset += chunkSize*2; - r.requestId = dbClient.query(queryForSortKeys, r.lastOffset, - chunkSize*2, partitionObjects[partitionIndex]->name()); + r.lastOffset += chunkSize; + QJsonDbReadRequest *request = keyRequests[partitionIndex]->newRequest(partitionIndex); + request->setQuery(queryForSortKeys); + request->setProperty("queryOffset", r.lastOffset); + request->setQueryLimit(chunkSize); + request->setPartition(partitionObjects[partitionIndex]->name()); + JsonDatabase::sharedConnection().send(request); + } void JsonDbCachingListModelPrivate::fetchNextChunk(int partitionIndex) { RequestInfo &r = partitionObjectDetails[partitionIndex]; - r.requestId = dbClient.query(query+sortOrder, r.lastOffset, - qMin(r.requestCount, chunkSize), - partitionObjects[partitionIndex]->name()); + QJsonDbReadRequest *request = valueRequests[partitionIndex]->newRequest(partitionIndex); + request->setQuery(query+sortOrder); + request->setProperty("queryOffset", r.lastOffset); + request->setQueryLimit(qMin(r.requestCount, chunkSize)); + request->setPartition(partitionObjects[partitionIndex]->name()); + JsonDatabase::sharedConnection().send(request); + } void JsonDbCachingListModelPrivate::prefetchNearbyPages(int index) @@ -688,15 +691,14 @@ void JsonDbCachingListModelPrivate::requestPageContaining(int index) } - void JsonDbCachingListModelPrivate::clearNotification(int index) { if (index >= partitionObjects.count()) return; RequestInfo &r = partitionObjectDetails[index]; - if (!r.notifyUuid.isEmpty()) { - dbClient.unregisterNotification(r.notifyUuid); + if (r.watcher) { + JsonDatabase::sharedConnection().removeWatcher(r.watcher); } r.clear(); } @@ -713,13 +715,16 @@ void JsonDbCachingListModelPrivate::createOrUpdateNotification(int index) if (index >= partitionObjects.count()) return; clearNotification(index); - JsonDbClient::NotifyTypes notifyActions = JsonDbClient::NotifyCreate - | JsonDbClient::NotifyUpdate| JsonDbClient::NotifyRemove; - partitionObjectDetails[index].notifyUuid= dbClient.registerNotification( - notifyActions , query, partitionObjects[index]->name(), - q, SLOT(_q_dbNotified(QString,QtAddOn::JsonDb::JsonDbNotification)), - q, SLOT(_q_dbNotifyReadyResponse(int,QVariant)), - SLOT(_q_dbNotifyErrorResponse(int,int,QString))); + QJsonDbWatcher *watcher = new QJsonDbWatcher(); + watcher->setQuery(query+sortOrder); + watcher->setWatchedActions(QJsonDbWatcher::Created | QJsonDbWatcher::Updated |QJsonDbWatcher::Removed); + watcher->setPartition(partitionObjects[index]->name()); + QObject::connect(watcher, SIGNAL(notificationsAvailable(int)), + q, SLOT(_q_notificationsAvailable())); + QObject::connect(watcher, SIGNAL(error(QtJsonDb::QJsonDbWatcher::ErrorCode,QString)), + q, SLOT(_q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode,QString))); + JsonDatabase::sharedConnection().addWatcher(watcher); + partitionObjectDetails[index].watcher = watcher; } void JsonDbCachingListModelPrivate::createOrUpdateNotifications() @@ -733,23 +738,14 @@ void JsonDbCachingListModelPrivate::parseSortOrder() { Q_Q(JsonDbCachingListModel); QRegExp orderMatch("\\[([/\\\\[\\]])[ ]*([^\\[\\]]+)[ ]*\\]"); - ascendingOrders.clear(); - orderProperties.clear(); - orderPaths.clear(); - int matchIndex = 0, firstMatch = -1; - while ((matchIndex = orderMatch.indexIn(sortOrder, matchIndex)) >= 0) { - bool ascendingOrder = false; + if (orderMatch.indexIn(sortOrder, 0) >= 0) { + ascendingOrder = false; if (!orderMatch.cap(1).compare(QLatin1String("/"))) ascendingOrder = true; - ascendingOrders << ascendingOrder; - orderProperties << orderMatch.cap(2); - orderPaths << orderMatch.cap(2).split('.'); - if (firstMatch == -1) - firstMatch = matchIndex; - matchIndex += orderMatch.matchedLength(); - } - if (orderProperties.count()) { - queryForIndexSpec = QString(QLatin1String("[?_type=\"Index\"][?name=\"%1\"]")).arg(orderProperties[0]); + indexName = orderMatch.cap(2); + } + if (!indexName.isEmpty()) { + queryForIndexSpec = QString(QLatin1String("[?_type=\"Index\"][?name=\"%1\"]")).arg(indexName); } else { // Set default sort order (by _uuid) q->setSortOrder(QLatin1String("[/_uuid]")); @@ -760,45 +756,15 @@ void JsonDbCachingListModelPrivate::setQueryForSortKeys() { // Query to retrieve the sortKeys // TODO remove the "[= {}]" from query - queryForSortKeys = query + QLatin1String("[= [ _uuid"); - for (int i = 0; i < orderProperties.count() ; i++) { - queryForSortKeys += QLatin1String(", ") + orderProperties[i]; - } - queryForSortKeys += QLatin1String("]]"); + queryForSortKeys = query + QLatin1String("[= { _uuid: _uuid"); + queryForSortKeys += QLatin1String("}]"); queryForSortKeys += sortOrder; } -int JsonDbCachingListModelPrivate::indexOfKeyIndexSpecId(int requestId) -{ - for (int i = 0; i < partitionIndexDetails.count(); i++) { - if (requestId == partitionIndexDetails[i].requestId) - return i; - } - return -1; -} - -int JsonDbCachingListModelPrivate::indexOfKeyRequestId(int requestId) -{ - for (int i = 0; i < partitionKeyRequestDetails.count(); i++) { - if (requestId == partitionKeyRequestDetails[i].requestId) - return i; - } - return -1; -} - -int JsonDbCachingListModelPrivate::indexOfRequestId(int requestId) -{ - for (int i = 0; i < partitionObjectDetails.count(); i++) { - if (requestId == partitionObjectDetails[i].requestId) - return i; - } - return -1; -} - -int JsonDbCachingListModelPrivate::indexOfNotifyUUID(const QString& notifyUuid) +int JsonDbCachingListModelPrivate::indexOfWatcher(QJsonDbWatcher *watcher) { for (int i = 0; i < partitionObjectDetails.count(); i++) { - if (notifyUuid == partitionObjectDetails[i].notifyUuid) + if (watcher == partitionObjectDetails[i].watcher) return i; } return -1; @@ -841,7 +807,7 @@ QVariant JsonDbCachingListModelPrivate::getItem(int index) } if (state == JsonDbCachingListModel::Ready) // Pre-fetch only, if in Ready state prefetchNearbyPages(index); - return QVariant(objectCache.valueAtPage(page, uuid)); + return QVariant(objectCache.valueAtPage(page, uuid).toVariantMap()); } QVariant JsonDbCachingListModelPrivate::getItem(int index, int role) @@ -909,40 +875,66 @@ int JsonDbCachingListModelPrivate::indexOf(const QString &uuid) const return iterator_position(begin, end, i); } -void JsonDbCachingListModelPrivate::sendNotifications(const QString& currentNotifyUuid, const QVariant &v, JsonDbClient::NotifyType action) +void JsonDbCachingListModelPrivate::sendNotification(int partitionIndex, const QJsonObject &object, QJsonDbWatcher::Action action) { - int idx = indexOfNotifyUUID(currentNotifyUuid); - if (idx == -1) - return; - - const QVariantMap &item = v.toMap(); - if (action == JsonDbClient::NotifyCreate) { - addItem(item, idx); - } else if (action == JsonDbClient::NotifyRemove) { - deleteItem(item, idx); - } else if (action == JsonDbClient::NotifyUpdate) { - updateItem(item, idx); + if (action == QJsonDbWatcher::Created) { + addItem(object, partitionIndex); + } else if (action == QJsonDbWatcher::Removed) + deleteItem(object, partitionIndex); + else if (action == QJsonDbWatcher::Updated) { + updateItem(object, partitionIndex); } } -void JsonDbCachingListModelPrivate::_q_jsonDbResponse(int id, const QVariant &v) +void JsonDbCachingListModelPrivate::_q_keyResponse(int index, const QList<QJsonObject> &v, const QString &sortKey) { - int idx = -1; - if ((idx = indexOfKeyRequestId(id)) != -1) { - partitionKeyRequestDetails[idx].requestId = -1; - partitionObjectDetails[idx].requestId = -1; - fillKeys(v, idx); - } else if ((idx = indexOfRequestId(id)) != -1) { - partitionObjectDetails[idx].requestId = -1; - fillData(v, idx); - } else if ((idx = indexOfKeyIndexSpecId(id)) != -1) { - partitionIndexDetails[idx].requestId = -1; - verifyIndexSpec(v, idx); - } +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif + Q_UNUSED(sortKey) + fillKeys(v, index); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif +} + +void JsonDbCachingListModelPrivate::_q_valueResponse(int index, const QList<QJsonObject> &v) +{ +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif + fillData(v, index); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } -void JsonDbCachingListModelPrivate::_q_jsonDbErrorResponse(int, int code, const QString &message) +void JsonDbCachingListModelPrivate::_q_indexResponse(int index, const QList<QJsonObject> &v) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif + verifyIndexSpec(v, index); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif +} + +void JsonDbCachingListModelPrivate::_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message) +{ +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_Q(JsonDbCachingListModel); qWarning() << QString("JsonDb error: %1 %2").arg(code).arg(message); int oldErrorCode = errorCode; @@ -950,28 +942,55 @@ void JsonDbCachingListModelPrivate::_q_jsonDbErrorResponse(int, int code, const errorString = message; if (oldErrorCode != errorCode) emit q->errorChanged(q->error()); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } -void JsonDbCachingListModelPrivate::_q_dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification) +void JsonDbCachingListModelPrivate::_q_notificationsAvailable() { - if (state == JsonDbCachingListModel::Querying) { - NotifyItem pending; - pending.notifyUuid = notify_uuid; - pending.item = _notification.object(); - pending.action = _notification.action(); - pendingNotifications.append(pending); - } else if (state == JsonDbCachingListModel::Ready) { - sendNotifications(notify_uuid, _notification.object(), _notification.action()); +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif + Q_Q(JsonDbCachingListModel); + QJsonDbWatcher *watcher = qobject_cast<QJsonDbWatcher *>(q->sender()); + int partitionIndex = indexOfWatcher(watcher); + if (!watcher || partitionIndex == -1) + return; + QList<QJsonDbNotification> list = watcher->takeNotifications(); + for (int i = 0; i < list.count(); i++) { + const QJsonDbNotification & notification = list[i]; + QJsonObject object = notification.object(); + QJsonDbWatcher::Action action = notification.action(); + if (state == JsonDbCachingListModel::Querying) { + NotificationItem pending; + pending.partitionIndex = partitionIndex; + pending.item = object; + pending.action = action; + pendingNotifications.append(pending); + } else { + foreach (NotificationItem pending, pendingNotifications) + sendNotification(pending.partitionIndex, pending.item, pending.action); + pendingNotifications.clear(); + sendNotification(partitionIndex, object, action); + } } +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } -void JsonDbCachingListModelPrivate::_q_dbNotifyReadyResponse(int /* id */, const QVariant &/* result */) -{ -} - -void JsonDbCachingListModelPrivate::_q_dbNotifyErrorResponse(int id, int code, const QString &message) +void JsonDbCachingListModelPrivate::_q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message) { - Q_UNUSED(id); +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_Q(JsonDbCachingListModel); qWarning() << QString("JsonDbCachingListModel Notification error: %1 %2").arg(code).arg(message); int oldErrorCode = errorCode; @@ -979,23 +998,27 @@ void JsonDbCachingListModelPrivate::_q_dbNotifyErrorResponse(int id, int code, c errorString = message; if (oldErrorCode != errorCode) emit q->errorChanged(q->error()); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } void JsonDbCachingListModelPrivate::_q_verifyDefaultIndexType(int index) { - if (!orderProperties.count()) - return; - QString indexName = orderProperties[0]; +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif SortIndexSpec &indexSpec = partitionIndexDetails[index].spec; partitionIndexDetails[index].valid = true; if (!indexName.compare(QLatin1String("_uuid"))) { - indexSpec.propertyName = QLatin1String("_uuid"); - indexSpec.propertyType = QLatin1String("_uuid"); + indexSpec.name = QLatin1String("_uuid"); indexSpec.type = SortIndexSpec::UUID; indexSpec.caseSensitive = false; } else if (!indexName.compare(QLatin1String("_type"))) { - indexSpec.propertyName = QLatin1String("_type"); - indexSpec.propertyType = QLatin1String("_type"); + indexSpec.name = QLatin1String("_type"); indexSpec.type = SortIndexSpec::String; indexSpec.caseSensitive = true; } @@ -1009,12 +1032,56 @@ void JsonDbCachingListModelPrivate::_q_verifyDefaultIndexType(int index) } if (checkedAll) { //Start fetching the keys. - orderProperties[0] = indexSpec.propertyName; setQueryForSortKeys(); for (int i = 0; i < partitionKeyRequestDetails.count(); i++) { fetchPartitionKeys(i); } } +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif +} + +void JsonDbCachingListModelPrivate::appendPartition(JsonDbPartition *v) +{ + Q_Q(JsonDbCachingListModel); + partitionObjects.append(QPointer<JsonDbPartition>(v)); + + partitionObjectDetails.append(RequestInfo()); + ModelRequest *valueRequest = new ModelRequest(); + QObject::connect(valueRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_valueResponse(int,QList<QJsonObject>))); + QObject::connect(valueRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + valueRequests.append(valueRequest); + + partitionKeyRequestDetails.append(RequestInfo()); + ModelRequest *keyRequest = new ModelRequest(); + QObject::connect(keyRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_keyResponse(int,QList<QJsonObject>,QString))); + QObject::connect(keyRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + keyRequests.append(keyRequest); + + partitionObjectUuids.append(JsonDbModelIndexType()); + + partitionIndexDetails.append(IndexInfo()); + ModelRequest *indexRequest = new ModelRequest(); + QObject::connect(indexRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_indexResponse(int,QList<QJsonObject>))); + QObject::connect(indexRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + indexRequests.append(indexRequest); + + if (componentComplete && !query.isEmpty()) { + parseSortOrder(); + createOrUpdateNotification(partitionObjects.count()-1); + if (state == JsonDbCachingListModel::None) + resetModel = true; + fetchIndexSpec(partitionObjects.count()-1); + } } void JsonDbCachingListModelPrivate::partitions_append(QQmlListProperty<JsonDbPartition> *p, JsonDbPartition *v) @@ -1022,18 +1089,7 @@ void JsonDbCachingListModelPrivate::partitions_append(QQmlListProperty<JsonDbPar JsonDbCachingListModel *q = qobject_cast<JsonDbCachingListModel *>(p->object); JsonDbCachingListModelPrivate *pThis = (q) ? q->d_func() : 0; if (pThis) { - pThis->partitionObjects.append(QPointer<JsonDbPartition>(v));\ - pThis->partitionObjectDetails.append(RequestInfo()); - pThis->partitionKeyRequestDetails.append(RequestInfo()); - pThis->partitionObjectUuids.append(JsonDbModelIndexType()); - pThis->partitionIndexDetails.append(IndexInfo()); - if (pThis->componentComplete && !pThis->query.isEmpty()) { - pThis->parseSortOrder(); - pThis->createOrUpdateNotification(pThis->partitionObjects.count()-1); - if (pThis->state == JsonDbCachingListModel::None) - pThis->resetModel = true; - pThis->fetchIndexSpec(pThis->partitionObjects.count()-1); - } + pThis->appendPartition(v); } } @@ -1057,17 +1113,34 @@ JsonDbPartition* JsonDbCachingListModelPrivate::partitions_at(QQmlListProperty<J return 0; } +void JsonDbCachingListModelPrivate::clearPartitions() +{ + partitionObjects.clear(); + partitionObjectDetails.clear(); + partitionKeyRequestDetails.clear(); + partitionObjectUuids.clear(); + partitionIndexDetails.clear(); + while (!keyRequests.isEmpty()) { + delete keyRequests[0]; + keyRequests.removeFirst(); + } + while (!indexRequests.isEmpty()) { + delete indexRequests[0]; + indexRequests.removeFirst(); + } + while (!valueRequests.isEmpty()) { + delete valueRequests[0]; + valueRequests.removeFirst(); + } + reset(); +} + void JsonDbCachingListModelPrivate::partitions_clear(QQmlListProperty<JsonDbPartition> *p) { JsonDbCachingListModel *q = qobject_cast<JsonDbCachingListModel *>(p->object); JsonDbCachingListModelPrivate *pThis = (q) ? q->d_func() : 0; if (pThis) { - pThis->partitionObjects.clear(); - pThis->partitionObjectDetails.clear(); - pThis->partitionKeyRequestDetails.clear(); - pThis->partitionObjectUuids.clear(); - pThis->partitionIndexDetails.clear(); - pThis->reset(); + pThis->clearPartitions(); } } @@ -1124,8 +1197,17 @@ JsonDbCachingListModel::JsonDbCachingListModel(QObject *parent) : QAbstractListModel(parent) , d_ptr(new JsonDbCachingListModelPrivate(this)) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); d->init(); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } JsonDbCachingListModel::~JsonDbCachingListModel() @@ -1138,12 +1220,21 @@ void JsonDbCachingListModel::classBegin() void JsonDbCachingListModel::componentComplete() { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); d->componentComplete = true; if (!d->query.isEmpty() && d->partitionObjects.count()) { d->createOrUpdateNotifications(); d->fetchModel(); } +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1159,8 +1250,18 @@ int JsonDbCachingListModel::rowCount(const QModelIndex &parent) const QVariant JsonDbCachingListModel::data(const QModelIndex &modelIndex, int role) const { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif JsonDbCachingListModel *pThis = const_cast<JsonDbCachingListModel *>(this); - return pThis->d_func()->getItem(modelIndex.row(), role); + QVariant ret = pThis->d_func()->getItem(modelIndex.row(), role); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif + return ret; } /*! @@ -1224,6 +1325,10 @@ QVariant JsonDbCachingListModel::scriptableRoleNames() const void JsonDbCachingListModel::setScriptableRoleNames(const QVariant &vroles) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); d->properties.clear(); d->roleNames.clear(); @@ -1247,6 +1352,11 @@ void JsonDbCachingListModel::setScriptableRoleNames(const QVariant &vroles) } } QAbstractItemModel::setRoleNames(d->roleNames); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1277,6 +1387,10 @@ QString JsonDbCachingListModel::query() const void JsonDbCachingListModel::setQuery(const QString &newQuery) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); const QString oldQuery = d->query; @@ -1292,6 +1406,11 @@ void JsonDbCachingListModel::setQuery(const QString &newQuery) return; d->createOrUpdateNotifications(); d->fetchModel(); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1319,6 +1438,10 @@ int JsonDbCachingListModel::cacheSize() const void JsonDbCachingListModel::setCacheSize(int newCacheSize) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); if (newCacheSize == d->cacheSize) return; @@ -1332,10 +1455,19 @@ void JsonDbCachingListModel::setCacheSize(int newCacheSize) #ifdef JSONDB_LISTMODEL_DEBUG d->objectCache.dumpCacheDetails(); #endif +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } void JsonDbCachingListModel::partitionNameChanged(const QString &partitionName) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_UNUSED(partitionName); Q_D(JsonDbCachingListModel); @@ -1344,6 +1476,11 @@ void JsonDbCachingListModel::partitionNameChanged(const QString &partitionName) d->createOrUpdateNotifications(); d->fetchModel(); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1402,6 +1539,10 @@ QString JsonDbCachingListModel::sortOrder() const void JsonDbCachingListModel::setSortOrder(const QString &newSortOrder) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); const QString oldSortOrder = d->sortOrder; @@ -1413,6 +1554,11 @@ void JsonDbCachingListModel::setSortOrder(const QString &newSortOrder) d->createOrUpdateNotifications(); d->fetchModel(); } +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1477,8 +1623,17 @@ int JsonDbCachingListModel::indexOf(const QString &uuid) const */ void JsonDbCachingListModel::get(int index, const QJSValue &callback) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); d->queueGetCallback(index, callback); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! |