access/qnetworkaccesscache.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtNetwork module of the Qt Toolkit. -
7** -
8** $QT_BEGIN_LICENSE:LGPL$ -
9** Commercial License Usage -
10** Licensees holding valid commercial Qt licenses may use this file in -
11** accordance with the commercial license agreement provided with the -
12** Software or, alternatively, in accordance with the terms contained in -
13** a written agreement between you and Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/contact-us. -
16** -
17** GNU Lesser General Public License Usage -
18** Alternatively, this file may be used under the terms of the GNU Lesser -
19** General Public License version 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qnetworkaccesscache_p.h" -
43#include "QtCore/qpointer.h" -
44#include "QtCore/qdatetime.h" -
45#include "QtCore/qqueue.h" -
46#include "qnetworkaccessmanager_p.h" -
47#include "qnetworkreply_p.h" -
48#include "qnetworkrequest.h" -
49 -
50QT_BEGIN_NAMESPACE -
51 -
52enum ExpiryTimeEnum { -
53 ExpiryTime = 120 -
54}; -
55 -
56namespace { -
57 struct Receiver -
58 { -
59 QPointer<QObject> object; -
60 const char *member; -
61 }; -
62} -
63 -
64// idea copied from qcache.h -
65struct QNetworkAccessCache::Node -
66{ -
67 QDateTime timestamp; -
68 QQueue<Receiver> receiverQueue; -
69 QByteArray key; -
70 -
71 Node *older, *newer; -
72 CacheableObject *object; -
73 -
74 int useCount; -
75 -
76 Node() -
77 : older(0), newer(0), object(0), useCount(0) -
78 { }
executed: }
Execution Count:848
848
79}; -
80 -
81QNetworkAccessCache::CacheableObject::CacheableObject() -
82{ -
83 // leave the members uninitialized -
84 // they must be initialized by the derived class's constructor -
85} -
86 -
87QNetworkAccessCache::CacheableObject::~CacheableObject() -
88{ -
89#if 0 //def QT_DEBUG -
90 if (!key.isEmpty() && Ptr()->hasEntry(key)) -
91 qWarning() << "QNetworkAccessCache: object" << (void*)this << "key" << key -
92 << "destroyed without being removed from cache first!"; -
93#endif -
94} -
95 -
96void QNetworkAccessCache::CacheableObject::setExpires(bool enable) -
97{ -
98 expires = enable;
executed (the execution status of this line is deduced): expires = enable;
-
99}
executed: }
Execution Count:857
857
100 -
101void QNetworkAccessCache::CacheableObject::setShareable(bool enable) -
102{ -
103 shareable = enable;
executed (the execution status of this line is deduced): shareable = enable;
-
104}
executed: }
Execution Count:857
857
105 -
106QNetworkAccessCache::QNetworkAccessCache() -
107 : oldest(0), newest(0) -
108{ -
109}
executed: }
Execution Count:675
675
110 -
111QNetworkAccessCache::~QNetworkAccessCache() -
112{ -
113 clear();
executed (the execution status of this line is deduced): clear();
-
114}
executed: }
Execution Count:675
675
115 -
116void QNetworkAccessCache::clear() -
117{ -
118 NodeHash hashCopy = hash;
executed (the execution status of this line is deduced): NodeHash hashCopy = hash;
-
119 hash.clear();
executed (the execution status of this line is deduced): hash.clear();
-
120 -
121 // remove all entries -
122 NodeHash::Iterator it = hashCopy.begin();
executed (the execution status of this line is deduced): NodeHash::Iterator it = hashCopy.begin();
-
123 NodeHash::Iterator end = hashCopy.end();
executed (the execution status of this line is deduced): NodeHash::Iterator end = hashCopy.end();
-
124 for ( ; it != end; ++it) {
evaluated: it != end
TRUEFALSE
yes
Evaluation Count:846
yes
Evaluation Count:3027
846-3027
125 it->object->key.clear();
executed (the execution status of this line is deduced): it->object->key.clear();
-
126 it->object->dispose();
executed (the execution status of this line is deduced): it->object->dispose();
-
127 }
executed: }
Execution Count:846
846
128 -
129 // now delete: -
130 hashCopy.clear();
executed (the execution status of this line is deduced): hashCopy.clear();
-
131 -
132 timer.stop();
executed (the execution status of this line is deduced): timer.stop();
-
133 -
134 oldest = newest = 0;
executed (the execution status of this line is deduced): oldest = newest = 0;
-
135}
executed: }
Execution Count:3027
3027
136 -
137/*! -
138 Appends the entry given by \a key to the end of the linked list. -
139 (i.e., makes it the newest entry) -
140 */ -
141void QNetworkAccessCache::linkEntry(const QByteArray &key) -
142{ -
143 NodeHash::Iterator it = hash.find(key);
executed (the execution status of this line is deduced): NodeHash::Iterator it = hash.find(key);
-
144 if (it == hash.end())
partially evaluated: it == hash.end()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:631
0-631
145 return;
never executed: return;
0
146 -
147 Node *const node = &it.value();
executed (the execution status of this line is deduced): Node *const node = &it.value();
-
148 Q_ASSERT(node != oldest && node != newest);
executed (the execution status of this line is deduced): qt_noop();
-
149 Q_ASSERT(node->older == 0 && node->newer == 0);
executed (the execution status of this line is deduced): qt_noop();
-
150 Q_ASSERT(node->useCount == 0);
executed (the execution status of this line is deduced): qt_noop();
-
151 -
152 if (newest) {
evaluated: newest
TRUEFALSE
yes
Evaluation Count:3
yes
Evaluation Count:628
3-628
153 Q_ASSERT(newest->newer == 0);
executed (the execution status of this line is deduced): qt_noop();
-
154 newest->newer = node;
executed (the execution status of this line is deduced): newest->newer = node;
-
155 node->older = newest;
executed (the execution status of this line is deduced): node->older = newest;
-
156 }
executed: }
Execution Count:3
3
157 if (!oldest) {
evaluated: !oldest
TRUEFALSE
yes
Evaluation Count:628
yes
Evaluation Count:3
3-628
158 // there are no entries, so this is the oldest one too -
159 oldest = node;
executed (the execution status of this line is deduced): oldest = node;
-
160 }
executed: }
Execution Count:628
628
161 -
162 node->timestamp = QDateTime::currentDateTime().addSecs(ExpiryTime);
executed (the execution status of this line is deduced): node->timestamp = QDateTime::currentDateTime().addSecs(ExpiryTime);
-
163 newest = node;
executed (the execution status of this line is deduced): newest = node;
-
164}
executed: }
Execution Count:631
631
165 -
166/*! -
167 Removes the entry pointed by \a key from the linked list. -
168 Returns true if the entry removed was the oldest one. -
169 */ -
170bool QNetworkAccessCache::unlinkEntry(const QByteArray &key) -
171{ -
172 NodeHash::Iterator it = hash.find(key);
executed (the execution status of this line is deduced): NodeHash::Iterator it = hash.find(key);
-
173 if (it == hash.end())
evaluated: it == hash.end()
TRUEFALSE
yes
Evaluation Count:848
yes
Evaluation Count:100
100-848
174 return false;
executed: return false;
Execution Count:848
848
175 -
176 Node *const node = &it.value();
executed (the execution status of this line is deduced): Node *const node = &it.value();
-
177 -
178 bool wasOldest = false;
executed (the execution status of this line is deduced): bool wasOldest = false;
-
179 if (node == oldest) {
evaluated: node == oldest
TRUEFALSE
yes
Evaluation Count:89
yes
Evaluation Count:11
11-89
180 oldest = node->newer;
executed (the execution status of this line is deduced): oldest = node->newer;
-
181 wasOldest = true;
executed (the execution status of this line is deduced): wasOldest = true;
-
182 }
executed: }
Execution Count:89
89
183 if (node == newest)
evaluated: node == newest
TRUEFALSE
yes
Evaluation Count:88
yes
Evaluation Count:12
12-88
184 newest = node->older;
executed: newest = node->older;
Execution Count:88
88
185 if (node->older)
partially evaluated: node->older
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:100
0-100
186 node->older->newer = node->newer;
never executed: node->older->newer = node->newer;
0
187 if (node->newer)
evaluated: node->newer
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:99
1-99
188 node->newer->older = node->older;
executed: node->newer->older = node->older;
Execution Count:1
1
189 -
190 node->newer = node->older = 0;
executed (the execution status of this line is deduced): node->newer = node->older = 0;
-
191 return wasOldest;
executed: return wasOldest;
Execution Count:100
100
192} -
193 -
194void QNetworkAccessCache::updateTimer() -
195{ -
196 timer.stop();
executed (the execution status of this line is deduced): timer.stop();
-
197 -
198 if (!oldest)
evaluated: !oldest
TRUEFALSE
yes
Evaluation Count:88
yes
Evaluation Count:629
88-629
199 return;
executed: return;
Execution Count:88
88
200 -
201 int interval = QDateTime::currentDateTime().secsTo(oldest->timestamp);
executed (the execution status of this line is deduced): int interval = QDateTime::currentDateTime().secsTo(oldest->timestamp);
-
202 if (interval <= 0) {
partially evaluated: interval <= 0
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:629
0-629
203 interval = 0;
never executed (the execution status of this line is deduced): interval = 0;
-
204 } else {
never executed: }
0
205 // round up the interval -
206 interval = (interval + 15) & ~16;
executed (the execution status of this line is deduced): interval = (interval + 15) & ~16;
-
207 }
executed: }
Execution Count:629
629
208 -
209 timer.start(interval * 1000, this);
executed (the execution status of this line is deduced): timer.start(interval * 1000, this);
-
210}
executed: }
Execution Count:629
629
211 -
212bool QNetworkAccessCache::emitEntryReady(Node *node, QObject *target, const char *member) -
213{ -
214 if (!connect(this, SIGNAL(entryReady(QNetworkAccessCache::CacheableObject*)),
partially evaluated: !connect(this, "2""entryReady(QNetworkAccessCache::CacheableObject*)", target, member, Qt::QueuedConnection)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
0-1
215 target, member, Qt::QueuedConnection))
partially evaluated: !connect(this, "2""entryReady(QNetworkAccessCache::CacheableObject*)", target, member, Qt::QueuedConnection)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
0-1
216 return false;
never executed: return false;
0
217 -
218 emit entryReady(node->object);
executed (the execution status of this line is deduced): entryReady(node->object);
-
219 disconnect(SIGNAL(entryReady(QNetworkAccessCache::CacheableObject*)));
executed (the execution status of this line is deduced): disconnect("2""entryReady(QNetworkAccessCache::CacheableObject*)");
-
220 -
221 return true;
executed: return true;
Execution Count:1
1
222} -
223 -
224void QNetworkAccessCache::timerEvent(QTimerEvent *) -
225{ -
226 // expire old items -
227 QDateTime now = QDateTime::currentDateTime();
never executed (the execution status of this line is deduced): QDateTime now = QDateTime::currentDateTime();
-
228 -
229 while (oldest && oldest->timestamp < now) {
never evaluated: oldest
never evaluated: oldest->timestamp < now
0
230 Node *next = oldest->newer;
never executed (the execution status of this line is deduced): Node *next = oldest->newer;
-
231 oldest->object->dispose();
never executed (the execution status of this line is deduced): oldest->object->dispose();
-
232 -
233 hash.remove(oldest->key); // oldest gets deleted
never executed (the execution status of this line is deduced): hash.remove(oldest->key);
-
234 oldest = next;
never executed (the execution status of this line is deduced): oldest = next;
-
235 }
never executed: }
0
236 -
237 // fixup the list -
238 if (oldest)
never evaluated: oldest
0
239 oldest->older = 0;
never executed: oldest->older = 0;
0
240 else -
241 newest = 0;
never executed: newest = 0;
0
242 -
243 updateTimer();
never executed (the execution status of this line is deduced): updateTimer();
-
244}
never executed: }
0
245 -
246void QNetworkAccessCache::addEntry(const QByteArray &key, CacheableObject *entry) -
247{ -
248 Q_ASSERT(!key.isEmpty());
executed (the execution status of this line is deduced): qt_noop();
-
249 -
250 if (unlinkEntry(key))
partially evaluated: unlinkEntry(key)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:857
0-857
251 updateTimer();
never executed: updateTimer();
0
252 -
253 Node &node = hash[key]; // create the entry in the hash if it didn't exist
executed (the execution status of this line is deduced): Node &node = hash[key];
-
254 if (node.useCount)
evaluated: node.useCount
TRUEFALSE
yes
Evaluation Count:9
yes
Evaluation Count:848
9-848
255 qWarning("QNetworkAccessCache::addEntry: overriding active cache entry '%s'",
executed: QMessageLogger("access/qnetworkaccesscache.cpp", 255, __PRETTY_FUNCTION__).warning("QNetworkAccessCache::addEntry: overriding active cache entry '%s'", key.constData());
Execution Count:9
9
256 key.constData());
executed: QMessageLogger("access/qnetworkaccesscache.cpp", 255, __PRETTY_FUNCTION__).warning("QNetworkAccessCache::addEntry: overriding active cache entry '%s'", key.constData());
Execution Count:9
9
257 if (node.object)
evaluated: node.object
TRUEFALSE
yes
Evaluation Count:9
yes
Evaluation Count:848
9-848
258 node.object->dispose();
executed: node.object->dispose();
Execution Count:9
9
259 node.object = entry;
executed (the execution status of this line is deduced): node.object = entry;
-
260 node.object->key = key;
executed (the execution status of this line is deduced): node.object->key = key;
-
261 node.key = key;
executed (the execution status of this line is deduced): node.key = key;
-
262 node.useCount = 1;
executed (the execution status of this line is deduced): node.useCount = 1;
-
263}
executed: }
Execution Count:857
857
264 -
265bool QNetworkAccessCache::hasEntry(const QByteArray &key) const -
266{ -
267 return hash.contains(key);
executed: return hash.contains(key);
Execution Count:662
662
268} -
269 -
270bool QNetworkAccessCache::requestEntry(const QByteArray &key, QObject *target, const char *member) -
271{ -
272 NodeHash::Iterator it = hash.find(key);
executed (the execution status of this line is deduced): NodeHash::Iterator it = hash.find(key);
-
273 if (it == hash.end())
evaluated: it == hash.end()
TRUEFALSE
yes
Evaluation Count:37
yes
Evaluation Count:1
1-37
274 return false; // no such entry
executed: return false;
Execution Count:37
37
275 -
276 Node *node = &it.value();
executed (the execution status of this line is deduced): Node *node = &it.value();
-
277 -
278 if (node->useCount > 0 && !node->object->shareable) {
partially evaluated: node->useCount > 0
TRUEFALSE
yes
Evaluation Count:1
no
Evaluation Count:0
partially evaluated: !node->object->shareable
TRUEFALSE
yes
Evaluation Count:1
no
Evaluation Count:0
0-1
279 // object is not shareable and is in use -
280 // queue for later use -
281 Q_ASSERT(node->older == 0 && node->newer == 0);
executed (the execution status of this line is deduced): qt_noop();
-
282 Receiver receiver;
executed (the execution status of this line is deduced): Receiver receiver;
-
283 receiver.object = target;
executed (the execution status of this line is deduced): receiver.object = target;
-
284 receiver.member = member;
executed (the execution status of this line is deduced): receiver.member = member;
-
285 node->receiverQueue.enqueue(receiver);
executed (the execution status of this line is deduced): node->receiverQueue.enqueue(receiver);
-
286 -
287 // request queued -
288 return true;
executed: return true;
Execution Count:1
1
289 } else { -
290 // node not in use or is shareable -
291 if (unlinkEntry(key))
never evaluated: unlinkEntry(key)
0
292 updateTimer();
never executed: updateTimer();
0
293 -
294 ++node->useCount;
never executed (the execution status of this line is deduced): ++node->useCount;
-
295 return emitEntryReady(node, target, member);
never executed: return emitEntryReady(node, target, member);
0
296 } -
297} -
298 -
299QNetworkAccessCache::CacheableObject *QNetworkAccessCache::requestEntryNow(const QByteArray &key) -
300{ -
301 NodeHash::Iterator it = hash.find(key);
executed (the execution status of this line is deduced): NodeHash::Iterator it = hash.find(key);
-
302 if (it == hash.end())
evaluated: it == hash.end()
TRUEFALSE
yes
Evaluation Count:507
yes
Evaluation Count:562
507-562
303 return 0;
executed: return 0;
Execution Count:507
507
304 if (it->useCount > 0) {
evaluated: it->useCount > 0
TRUEFALSE
yes
Evaluation Count:473
yes
Evaluation Count:89
89-473
305 if (it->object->shareable) {
partially evaluated: it->object->shareable
TRUEFALSE
yes
Evaluation Count:473
no
Evaluation Count:0
0-473
306 ++it->useCount;
executed (the execution status of this line is deduced): ++it->useCount;
-
307 return it->object;
executed: return it->object;
Execution Count:473
473
308 } -
309 -
310 // object in use and not shareable -
311 return 0;
never executed: return 0;
0
312 } -
313 -
314 // entry not in use, let the caller have it -
315 bool wasOldest = unlinkEntry(key);
executed (the execution status of this line is deduced): bool wasOldest = unlinkEntry(key);
-
316 ++it->useCount;
executed (the execution status of this line is deduced): ++it->useCount;
-
317 -
318 if (wasOldest)
partially evaluated: wasOldest
TRUEFALSE
yes
Evaluation Count:89
no
Evaluation Count:0
0-89
319 updateTimer();
executed: updateTimer();
Execution Count:89
89
320 return it->object;
executed: return it->object;
Execution Count:89
89
321} -
322 -
323void QNetworkAccessCache::releaseEntry(const QByteArray &key) -
324{ -
325 NodeHash::Iterator it = hash.find(key);
executed (the execution status of this line is deduced): NodeHash::Iterator it = hash.find(key);
-
326 if (it == hash.end()) {
partially evaluated: it == hash.end()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1105
0-1105
327 qWarning("QNetworkAccessCache::releaseEntry: trying to release key '%s' that is not in cache",
never executed (the execution status of this line is deduced): QMessageLogger("access/qnetworkaccesscache.cpp", 327, __PRETTY_FUNCTION__).warning("QNetworkAccessCache::releaseEntry: trying to release key '%s' that is not in cache",
-
328 key.constData());
never executed (the execution status of this line is deduced): key.constData());
-
329 return;
never executed: return;
0
330 } -
331 -
332 Node *node = &it.value();
executed (the execution status of this line is deduced): Node *node = &it.value();
-
333 Q_ASSERT(node->useCount > 0);
executed (the execution status of this line is deduced): qt_noop();
-
334 -
335 // are there other objects waiting? -
336 if (!node->receiverQueue.isEmpty()) {
evaluated: !node->receiverQueue.isEmpty()
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:1104
1-1104
337 // queue another activation -
338 Receiver receiver;
executed (the execution status of this line is deduced): Receiver receiver;
-
339 do { -
340 receiver = node->receiverQueue.dequeue();
executed (the execution status of this line is deduced): receiver = node->receiverQueue.dequeue();
-
341 } while (receiver.object.isNull() && !node->receiverQueue.isEmpty());
executed: }
Execution Count:1
partially evaluated: receiver.object.isNull()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
never evaluated: !node->receiverQueue.isEmpty()
0-1
342 -
343 if (!receiver.object.isNull()) {
partially evaluated: !receiver.object.isNull()
TRUEFALSE
yes
Evaluation Count:1
no
Evaluation Count:0
0-1
344 emitEntryReady(node, receiver.object, receiver.member);
executed (the execution status of this line is deduced): emitEntryReady(node, receiver.object, receiver.member);
-
345 return;
executed: return;
Execution Count:1
1
346 } -
347 }
never executed: }
0
348 -
349 if (!--node->useCount) {
evaluated: !--node->useCount
TRUEFALSE
yes
Evaluation Count:631
yes
Evaluation Count:473
473-631
350 // no objects waiting; add it back to the expiry list -
351 if (node->object->expires)
partially evaluated: node->object->expires
TRUEFALSE
yes
Evaluation Count:631
no
Evaluation Count:0
0-631
352 linkEntry(key);
executed: linkEntry(key);
Execution Count:631
631
353 -
354 if (oldest == node)
evaluated: oldest == node
TRUEFALSE
yes
Evaluation Count:628
yes
Evaluation Count:3
3-628
355 updateTimer();
executed: updateTimer();
Execution Count:628
628
356 }
executed: }
Execution Count:631
631
357}
executed: }
Execution Count:1104
1104
358 -
359void QNetworkAccessCache::removeEntry(const QByteArray &key) -
360{ -
361 NodeHash::Iterator it = hash.find(key);
executed (the execution status of this line is deduced): NodeHash::Iterator it = hash.find(key);
-
362 if (it == hash.end()) {
partially evaluated: it == hash.end()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2
0-2
363 qWarning("QNetworkAccessCache::removeEntry: trying to remove key '%s' that is not in cache",
never executed (the execution status of this line is deduced): QMessageLogger("access/qnetworkaccesscache.cpp", 363, __PRETTY_FUNCTION__).warning("QNetworkAccessCache::removeEntry: trying to remove key '%s' that is not in cache",
-
364 key.constData());
never executed (the execution status of this line is deduced): key.constData());
-
365 return;
never executed: return;
0
366 } -
367 -
368 Node *node = &it.value();
executed (the execution status of this line is deduced): Node *node = &it.value();
-
369 if (unlinkEntry(key))
partially evaluated: unlinkEntry(key)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2
0-2
370 updateTimer();
never executed: updateTimer();
0
371 if (node->useCount > 1)
partially evaluated: node->useCount > 1
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:2
0-2
372 qWarning("QNetworkAccessCache::removeEntry: removing active cache entry '%s'",
never executed: QMessageLogger("access/qnetworkaccesscache.cpp", 372, __PRETTY_FUNCTION__).warning("QNetworkAccessCache::removeEntry: removing active cache entry '%s'", key.constData());
0
373 key.constData());
never executed: QMessageLogger("access/qnetworkaccesscache.cpp", 372, __PRETTY_FUNCTION__).warning("QNetworkAccessCache::removeEntry: removing active cache entry '%s'", key.constData());
0
374 -
375 node->object->key.clear();
executed (the execution status of this line is deduced): node->object->key.clear();
-
376 hash.remove(node->key);
executed (the execution status of this line is deduced): hash.remove(node->key);
-
377}
executed: }
Execution Count:2
2
378 -
379QT_END_NAMESPACE -
380 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial