summaryrefslogtreecommitdiffstats
path: root/sinksh/syntax_modules/sink_selftest.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2018-02-15 10:19:08 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-02-15 11:08:52 +0100
commit531972042d4b610258c8af8a17ec3a99cd063dda (patch)
treeef4356ec141f0f1ccd756e8610b08553b866bf78 /sinksh/syntax_modules/sink_selftest.cpp
parentf51963f057bcbdd175114433913a1c5f0eebd546 (diff)
downloadsink-531972042d4b610258c8af8a17ec3a99cd063dda.tar.gz
sink-531972042d4b610258c8af8a17ec3a99cd063dda.zip
Fixed crashes due to concurrently running queries.
A single QueryRunner should never have multiple workers running at the same time. We did not properly enforce this in case of incremental updates coming in. The only way I managed to reproduce the crash: * Open a large folder with lots of unread mail in kube * Select a mail in the maillist and hold the down button * This will: * Repeatedly call fetch more * Trigger lot's of mark as read modifications that result in notifications. * Eventually it crashes somewhere in EntityStore, likely because of concurrent access of the filter structure which is shared through the state. We now ensure in the single threaded portion of the code that we only ever run one worker at a time. If we did receive an update during, we remember that change and fetch more once we're done. To be able to call fetch again that portion was also factored out into a separate function.
Diffstat (limited to 'sinksh/syntax_modules/sink_selftest.cpp')
-rw-r--r--sinksh/syntax_modules/sink_selftest.cpp84
1 files changed, 75 insertions, 9 deletions
diff --git a/sinksh/syntax_modules/sink_selftest.cpp b/sinksh/syntax_modules/sink_selftest.cpp
index 21dfbff..8ad4f60 100644
--- a/sinksh/syntax_modules/sink_selftest.cpp
+++ b/sinksh/syntax_modules/sink_selftest.cpp
@@ -46,28 +46,94 @@ bool selfTest(const QStringList &args_, State &state)
46 return false; 46 return false;
47 } 47 }
48 48
49 using namespace Sink::ApplicationDomain;
49 auto options = SyntaxTree::parseOptions(args_); 50 auto options = SyntaxTree::parseOptions(args_);
50 if (options.positionalArguments.contains("stresstest")) { 51 if (options.positionalArguments.contains("stresstest")) {
51 auto resource = SinkshUtils::parseUid(options.options.value("resource").first().toUtf8()); 52 auto resource = SinkshUtils::parseUid(options.options.value("resource").first().toUtf8());
52 qWarning() << "Stresstest on resource: " << resource; 53 qWarning() << "Stresstest on resource: " << resource;
53 Sink::Query query;
54 query.resourceFilter(resource);
55 query.limit(100);
56
57 auto models = QSharedPointer<QList<QSharedPointer<QAbstractItemModel>>>::create(); 54 auto models = QSharedPointer<QList<QSharedPointer<QAbstractItemModel>>>::create();
58 for (int i = 0; i < 50; i++) { 55
56 //Simulate the maillist, where we scroll down and trigger lots of fetchMore calls
57 {
58 Sink::Query query;
59 query.resourceFilter(resource);
60 query.limit(100);
61 query.request<Mail::Subject>();
62 query.request<Mail::Sender>();
63 query.request<Mail::To>();
64 query.request<Mail::Cc>();
65 query.request<Mail::Bcc>();
66 query.request<Mail::Date>();
67 query.request<Mail::Unread>();
68 query.request<Mail::Important>();
69 query.request<Mail::Draft>();
70 query.request<Mail::Sent>();
71 query.request<Mail::Trash>();
72 query.request<Mail::Folder>();
73 query.sort<Mail::Date>();
74 query.reduce<Mail::ThreadId>(Sink::Query::Reduce::Selector::max<Mail::Date>())
75 .count("count")
76 .collect<Mail::Unread>("unreadCollected")
77 .collect<Mail::Important>("importantCollected");
78
59 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query); 79 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query);
60 *models << model; 80 models->append(model);
61 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [models, model, &state](const QModelIndex &start, const QModelIndex &end, const QVector<int> &roles) { 81 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [models, model, &state](const QModelIndex &start, const QModelIndex &end, const QVector<int> &roles) {
62 if (roles.contains(Sink::Store::ChildrenFetchedRole)) { 82 if (roles.contains(Sink::Store::ChildrenFetchedRole)) {
63 models->removeAll(model); 83 if (!model->canFetchMore({})) {
64 qWarning() << "Model complete: " << models->count(); 84 qWarning() << "Model complete: " << models->count();
85 models->removeAll(model);
86 } else {
87 qWarning() << "Fetching more";
88 //Simulate superfluous fetchMore calls
89 for (int i = 0; i < 10; i++) {
90 model->fetchMore({});
91 }
92 return;
93 }
65 if (models->isEmpty()) { 94 if (models->isEmpty()) {
66 state.commandFinished(); 95 state.commandFinished();
67 } 96 }
68 } 97 }
69 }); 98 });
99
70 } 100 }
101
102 //Simluate lot's of mailviewers doing a bunch of queries
103 {
104 Sink::Query query;
105 query.resourceFilter(resource);
106 query.limit(10);
107 query.request<Mail::Subject>();
108 query.request<Mail::Sender>();
109 query.request<Mail::To>();
110 query.request<Mail::Cc>();
111 query.request<Mail::Bcc>();
112 query.request<Mail::Date>();
113 query.request<Mail::Unread>();
114 query.request<Mail::Important>();
115 query.request<Mail::Draft>();
116 query.request<Mail::Sent>();
117 query.request<Mail::Trash>();
118 query.request<Mail::Folder>();
119 query.sort<Sink::ApplicationDomain::Mail::Date>();
120 query.bloom<Sink::ApplicationDomain::Mail::ThreadId>();
121
122 for (int i = 0; i < 50; i++) {
123 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query);
124 *models << model;
125 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [models, model, &state](const QModelIndex &start, const QModelIndex &end, const QVector<int> &roles) {
126 if (roles.contains(Sink::Store::ChildrenFetchedRole)) {
127 models->removeAll(model);
128 qWarning() << "Model complete: " << models->count();
129 if (models->isEmpty()) {
130 state.commandFinished();
131 }
132 }
133 });
134 }
135 }
136
71 return true; 137 return true;
72 } 138 }
73 return false; 139 return false;