MythTV master
dsmcccache.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) David C.J. Matthews 2005, 2006
3 * Derived from libdsmcc by Richard Palmer
4 */
5#include <cstring> // For memcmp
6
7#include <QStringList>
8
10
11#include "dsmcccache.h"
12#include "dsmccbiop.h"
13#include "dsmccreceiver.h"
14#include "dsmcc.h"
15
32 // Delete all this when the cache is deleted.
33 : m_dsmcc(dsmcc)
34{
35}
36
38{
39 QMap<DSMCCCacheReference, DSMCCCacheDir*>::Iterator dir;
40 QMap<DSMCCCacheReference, DSMCCCacheFile*>::Iterator fil;
41
42 for (dir = m_directories.begin(); dir != m_directories.end(); ++dir)
43 delete *dir;
44
45 for (dir = m_gateways.begin(); dir != m_gateways.end(); ++dir)
46 delete *dir;
47
48 for (fil = m_files.begin(); fil != m_files.end(); ++fil)
49 delete *fil;
50}
51
52// Print out a key for debugging.
54{
55 QString result;
56 for (int i = 0; i < 4 && i < size(); i++)
57 result += QString("%1").arg(static_cast<uint>(at(i)), 2, 16, QChar('0'));
58 return result;
59}
60
61// Ordering function used in QMap
62bool operator < (const DSMCCCacheKey &key1, const DSMCCCacheKey &key2)
63{
64 const char *data1 = key1.data();
65 const char *data2 = key2.data();
66 uint size1 = key1.size();
67 uint size2 = key2.size();
68 uint size = 0;
69 if (size1 < size2)
70 size = size1;
71 else
72 size = size2;
73 int res = memcmp(data1, data2, size);
74 if (res < 0)
75 return true;
76 if (res > 0)
77 return false;
78
79 return size1 < size2;
80}
81
82// Test for equality of the cache references
83// which include the carousel and module ids.
85{
88}
89
91{
92 return p != nullptr && Equal(*p);
93}
94
95
96// Print out a cache reference for debugging.
98{
99 return QString("%1-%2-%3-")
100 .arg(m_nCarouselId).arg(m_nStreamTag)
101 .arg(m_nModuleId) + m_key.toString();
102}
103
104// Operator required for QMap
106 const DSMCCCacheReference &ref2)
107{
108 if (ref1.m_nCarouselId < ref2.m_nCarouselId)
109 return true;
110 if (ref1.m_nCarouselId > ref2.m_nCarouselId)
111 return false;
112 if (ref1.m_nStreamTag < ref2.m_nStreamTag)
113 return true;
114 if (ref1.m_nStreamTag > ref2.m_nStreamTag)
115 return false;
116 if (ref1.m_nModuleId < ref2.m_nModuleId)
117 return true;
118 if (ref1.m_nModuleId > ref2.m_nModuleId)
119 return false;
120 if (ref1.m_key < ref2.m_key)
121 return true;
122
123 return false;
124}
125
126// Create a gateway entry.
128{
129 // Check to see that it isn't already there. It shouldn't be.
130 QMap<DSMCCCacheReference, DSMCCCacheDir*>::Iterator dir =
131 m_gateways.find(ref);
132
133 if (dir != m_gateways.end())
134 {
135 LOG(VB_DSMCC, LOG_ERR, QString("[DSMCCCache] Already seen gateway %1")
136 .arg(ref.toString()));
137 return *dir;
138 }
139
140 LOG(VB_DSMCC, LOG_INFO, QString("[DSMCCCache] New gateway reference %1")
141 .arg(ref.toString()));
142
143 auto *pSrg = new DSMCCCacheDir(ref);
144 m_gateways.insert(ref, pSrg);
145
146 return pSrg;
147}
148
149// Create a directory entry.
151{
152 // Check to see that it isn't already there. It shouldn't be.
153 QMap<DSMCCCacheReference, DSMCCCacheDir*>::Iterator dir =
154 m_directories.find(ref);
155
156 if (dir != m_directories.end())
157 {
158 LOG(VB_DSMCC, LOG_ERR, QString("[DSMCCCache] Already seen directory %1")
159 .arg(ref.toString()));
160 return *dir;
161 }
162
163 LOG(VB_DSMCC, LOG_INFO, QString("[DSMCCCache] New directory reference %1")
164 .arg(ref.toString()));
165
166 auto *pDir = new DSMCCCacheDir(ref);
167 m_directories.insert(ref, pDir);
168
169 return pDir;
170}
171
172// Called when the data for a file module arrives.
174 const QByteArray &data)
175{
176 // Do we have the file already?
177 LOG(VB_DSMCC, LOG_INFO,
178 QString("[DSMCCCache] Adding file data size %1 for reference %2")
179 .arg(data.size()).arg(ref.toString()));
180
181 QMap<DSMCCCacheReference, DSMCCCacheFile*>::Iterator fil =
182 m_files.find(ref);
183
184 DSMCCCacheFile *pFile = nullptr;
185 if (fil == m_files.end())
186 {
187 pFile = new DSMCCCacheFile(ref);
188 m_files.insert(ref, pFile);
189 }
190 else
191 {
192 pFile = *fil;
193 }
194
195 pFile->m_contents = data; // Save the data (this is use-counted by Qt).
196}
197
198// Add a file to the directory.
200{
201 QString name;
202 name = QString::fromLatin1(pBB->m_name.m_comps[0].m_id
203 /*, pBB->m_name.m_comps[0].m_id_len*/);
204
205 const DSMCCCacheReference *entry =
207
208 pDir->m_files.insert(name, *entry);
209
210 LOG(VB_DSMCC, LOG_INFO,
211 QString("[DSMCCCache] Added file name %1 reference %2 parent %3")
212 .arg(name, entry->toString(), pDir->m_reference.toString()));
213}
214
215// Add a sub-directory to the directory.
217{
218 // Is it already there?
219 QString name;
220 name = QString::fromLatin1(pBB->m_name.m_comps[0].m_id
221 /*, pBB->m_name.m_comps[0].m_id_len*/);
222 const DSMCCCacheReference *entry =
224
225 pDir->m_subDirectories.insert(name, *entry);
226
227 LOG(VB_DSMCC, LOG_INFO,
228 QString("[DSMCCCache] added subdirectory name %1 reference %2 parent %3")
229 .arg(name, entry->toString(), pDir->m_reference.toString()));
230}
231
232// Find File, Directory or Gateway by reference.
234{
235 // Find a file.
236 QMap<DSMCCCacheReference, DSMCCCacheFile*>::Iterator fil =
237 m_files.find(ref);
238
239 if (fil == m_files.end())
240 return nullptr;
241
242 return *fil;
243}
244
246{
247 // Find a directory.
248 QMap<DSMCCCacheReference, DSMCCCacheDir*>::Iterator dir =
249 m_directories.find(ref);
250
251 if (dir == m_directories.end())
252 return nullptr;
253
254 return *dir;
255}
256
258{
259 // Find a gateway.
260 QMap<DSMCCCacheReference, DSMCCCacheDir*>::Iterator dir =
261 m_gateways.find(ref);
262
263 if (dir == m_gateways.end())
264 return nullptr;
265
266 return *dir;
267}
268
269
270// Return the contents of an object if it exists.
271// Returns zero for success, -1 if we know the object does not
272// currently exist and +1 if the carousel has not so far loaded
273// the object or one of the parent files.
274int DSMCCCache::GetDSMObject(QStringList &objectPath, QByteArray &result)
275{
277 if (dir == nullptr)
278 return 1; // No gateway yet.
279
280 QStringList::Iterator it = objectPath.begin();
281 while (it != objectPath.end())
282 {
283 QString name = *it;
284 ++it;
285 if (it == objectPath.end())
286 { // It's a leaf - look in the file names
287 QMap<QString, DSMCCCacheReference>::Iterator ref =
288 dir->m_files.find(name);
289
290 if (ref == dir->m_files.end())
291 return -1; // Not there.
292
293 DSMCCCacheFile *fil = FindFileData(*ref);
294
295 if (fil == nullptr) // Exists but not yet set.
296 return 1;
297
298 result = fil->m_contents;
299 return 0;
300 }
301
302 // It's a directory
303 QMap<QString, DSMCCCacheReference>::Iterator ref =
304 dir->m_subDirectories.find(name);
305
306 if (ref == dir->m_subDirectories.end())
307 return -1; // Not there
308
309 dir = FindDir(*ref);
310
311 if (dir == nullptr) // Exists but not yet set.
312 return 1;
313 // else search in this directory
314 }
315
316 return -1;
317}
318
319// Set the gateway reference from a DSI message.
321{
322 if (!m_gatewayRef.Equal(ref))
323 {
324 LOG(VB_DSMCC, LOG_INFO, QString("[DSMCCCache] Setting gateway to reference %1")
325 .arg(ref.toString()));
326 m_gatewayRef = ref;
327 }
328}
BiopName m_name
Definition: dsmccbiop.h:159
BiopIor m_ior
Definition: dsmccbiop.h:161
ProfileBody * m_profileBody
Definition: dsmccbiop.h:146
char * m_id
Definition: dsmccbiop.h:29
BiopNameComp * m_comps
Definition: dsmccbiop.h:42
DSMCCCacheReference m_reference
Definition: dsmcccache.h:72
QMap< QString, DSMCCCacheReference > m_files
Definition: dsmcccache.h:70
QMap< QString, DSMCCCacheReference > m_subDirectories
Definition: dsmcccache.h:69
QByteArray m_contents
Definition: dsmcccache.h:83
QString toString(void) const
Definition: dsmcccache.cpp:53
bool Equal(const DSMCCCacheReference &r) const
Definition: dsmcccache.cpp:84
QString toString(void) const
Definition: dsmcccache.cpp:97
unsigned short m_nStreamTag
Definition: dsmcccache.h:53
unsigned short m_nModuleId
Definition: dsmcccache.h:52
unsigned long m_nCarouselId
Definition: dsmcccache.h:51
DSMCCCacheKey m_key
Definition: dsmcccache.h:54
QMap< DSMCCCacheReference, DSMCCCacheDir * > m_gateways
Definition: dsmcccache.h:120
DSMCCCacheFile * FindFileData(const DSMCCCacheReference &ref)
Definition: dsmcccache.cpp:233
DSMCCCache(Dsmcc *dsmcc)
Definition: dsmcccache.cpp:31
static void AddDirInfo(DSMCCCacheDir *dir, const BiopBinding *pBB)
Definition: dsmcccache.cpp:216
void SetGateway(const DSMCCCacheReference &ref)
Definition: dsmcccache.cpp:320
static void AddFileInfo(DSMCCCacheDir *dir, const BiopBinding *pBB)
Definition: dsmcccache.cpp:199
DSMCCCacheDir * Srg(const DSMCCCacheReference &ref)
Definition: dsmcccache.cpp:127
DSMCCCacheDir * Directory(const DSMCCCacheReference &ref)
Definition: dsmcccache.cpp:150
DSMCCCacheDir * FindGateway(const DSMCCCacheReference &ref)
Definition: dsmcccache.cpp:257
DSMCCCacheReference m_gatewayRef
Definition: dsmcccache.h:116
QMap< DSMCCCacheReference, DSMCCCacheFile * > m_files
Definition: dsmcccache.h:121
void CacheFileData(const DSMCCCacheReference &ref, const QByteArray &data)
Definition: dsmcccache.cpp:173
DSMCCCacheDir * FindDir(const DSMCCCacheReference &ref)
Definition: dsmcccache.cpp:245
QMap< DSMCCCacheReference, DSMCCCacheDir * > m_directories
Definition: dsmcccache.h:119
int GetDSMObject(QStringList &objectPath, QByteArray &result)
Definition: dsmcccache.cpp:274
Definition: dsmcc.h:78
virtual DSMCCCacheReference * GetReference()=0
bool operator<(const DSMCCCacheKey &key1, const DSMCCCacheKey &key2)
Definition: dsmcccache.cpp:62
unsigned int uint
Definition: freesurround.h:24
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39