1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 #include "oscl_library_list.h"
19 #include "oscl_string.h"
20 #include "oscl_file_io.h"
21 #include "oscl_file_types.h"
22 #include "pvlogger.h"
23 #include "oscl_uuid.h"
24
25 #define HASH '#'
26 #define NEWLINE '\n'
27 #define OPEN_PAREN '('
28 #define CLOSE_PAREN ')'
29 #define QUOTE '"'
30 #define COMMA ','
31 #define OSCL_NUMBER_OF_SHARED_LIBS 16
32 #define BUFFER_SIZE 256
33
34
OsclLibraryList()35 OSCL_EXPORT_REF OsclLibraryList::OsclLibraryList()
36 {
37 ipLogger = PVLogger::GetLoggerObject("oscllib");
38 #if OSCL_LIBRARY_PERF_LOGGING
39 iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.oscllib.oscllibrarylist");
40 iLinesRead = 0;
41 iLibHit = 0;
42 #endif
43 int32 err = 0;
44 OSCL_TRY(err,
45 iLibList.reserve(OSCL_NUMBER_OF_SHARED_LIBS);
46 );
47 if (err)
48 {
49 iLibList.clear();
50 OSCL_LEAVE(err);
51 }
52
53 }
54
~OsclLibraryList()55 OSCL_EXPORT_REF OsclLibraryList::~OsclLibraryList()
56 {
57 #if OSCL_LIBRARY_PERF_LOGGING
58 iDiagnosticsLogger = NULL;
59 #endif
60 ipLogger = NULL;
61 iLibList.clear();
62 }
63
64 // This method actually parses through a dll config file, retrieving the paths
65 // of dlls which implement a specific OsclUuid
Populate(const OsclUuid & aInterfaceId,const OSCL_String & aConfigFile)66 OSCL_EXPORT_REF OsclLibStatus OsclLibraryList::Populate(const OsclUuid& aInterfaceId, const OSCL_String& aConfigFile)
67 {
68 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG,
69 (0, "OsclLibraryList::Populate '%s' IN", aConfigFile.get_cstr()));
70
71 // Open config file
72 Oscl_FileServer fileserver;
73 if (0 != fileserver.Connect())
74 {
75 // Failed to connect to file server, return failure
76 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_ERR,
77 (0, "OsclLibraryList::Populate - Unable to connect to fileserver"));
78 return OsclLibFail;
79 }
80 Oscl_File configFile;
81 if (0 != configFile.Open(aConfigFile.get_cstr(), Oscl_File::MODE_READ, fileserver))
82 {
83 // Failed to open config file, return failure
84 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_ERR,
85 (0, "OsclLibraryList::Populate - Unable to open configFile %s", aConfigFile.get_cstr()));
86 return OsclLibFail;
87 }
88
89 #if OSCL_LIBRARY_PERF_LOGGING
90 // Start collecting stats for current config file
91 iLinesRead = 0;
92 iLibHit = 0;
93 TICK starttime;
94 SET_TICK(starttime);
95 #endif
96
97 // Read in a byte at a time
98 uint8 buf[1];
99 while (1 == configFile.Read(buf, 1, 1))
100 {
101 if (HASH == buf[0])
102 {
103 #if OSCL_LIBRARY_PERF_LOGGING
104 iLinesRead++;
105 #endif
106 // Ignore comments - begin with '#'
107 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG,
108 (0, "OsclLibraryList::Populate - Found a comment, skipping"));
109 // Advance to end of line
110 while (1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE)
111 {
112 // ignore
113 }
114 }
115 else if (OPEN_PAREN == buf[0])
116 {
117 // Parse UUID from line - begins with "("
118 uint8 uuidBuf[BUFFER_SIZE];
119 int i = 0;
120 uuidBuf[i++] = buf[0];
121 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG,
122 (0, "OsclLibraryList::Populate - Found a (, reading uuid"));
123 // Read a character at a time - stop if newline or eof is reached or buffer is filled
124 while (i < BUFFER_SIZE && 1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE)
125 {
126 uuidBuf[i++] = buf[0];
127 if (CLOSE_PAREN == buf[0])
128 {
129 break;
130 }
131 }
132 uuidBuf[i] = '\0';
133 if (NEWLINE == buf[0])
134 {
135 #if OSCL_LIBRARY_PERF_LOGGING
136 iLinesRead++;
137 #endif
138 // Reached the end of line but did not find the closing parentheses
139 // Skip this malformed line
140 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING,
141 (0, "OsclLibraryList::Populate - incomplete uuid, skipping line"));
142 }
143 else if (BUFFER_SIZE == i && CLOSE_PAREN != buf[0])
144 {
145 // Buffer is filled but did not reach the end of UUID - skip this malformed line
146 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING,
147 (0, "OsclLibraryList::Populate - uuid too long, skipping line"));
148 // Advance to end of line
149 while (1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE)
150 {
151 // ignore
152 }
153 }
154 else
155 {
156 // Create an instance of OsclUuid
157 OsclUuid tempUuidStr((char*)uuidBuf);
158 if (tempUuidStr == aInterfaceId)
159 {
160 // Parse path from line
161 bool commaFound = false;
162 bool quoteFound = false;
163 while (!(commaFound && quoteFound) && 1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE)
164 {
165 // Advance past ',' and '"'
166 if (COMMA == buf[0])
167 {
168 // If already found a comma, break and skip this malformed line
169 if (commaFound) break;
170 commaFound = true;
171 }
172 else if (QUOTE == buf[0])
173 {
174 // If already found a quote, break and skip this malformed line
175 if (quoteFound) break;
176 quoteFound = true;
177 }
178 }
179 if (!(commaFound && quoteFound) || NEWLINE == buf[0])
180 {
181 #if OSCL_LIBRARY_PERF_LOGGING
182 iLinesRead++;
183 #endif
184 // Did not find both ',' and '"' - Skip this malformed line
185 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING,
186 (0, "OsclLibraryList::Populate - missing ' or \", skipping line"));
187 }
188 else
189 {
190 uint8 pathBuf[BUFFER_SIZE];
191 i = 0;
192 // Read a character at a time - stop if newline is reached, ending quote is reached, or buffer is filled
193 // - leave room for terminating null character in buffer
194 while (1 == configFile.Read(buf, 1, 1) && buf[0] != QUOTE && buf[0] != NEWLINE && i < (BUFFER_SIZE - 1))
195 {
196 pathBuf[i++] = buf[0];
197 }
198 if (NEWLINE == buf[0])
199 {
200 #if OSCL_LIBRARY_PERF_LOGGING
201 iLinesRead++;
202 #endif
203 // Reached the end of line but did not find the closing quote
204 // Skip this malformed line
205 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING,
206 (0, "OsclLibraryList::Populate - incomplete path, skipping line"));
207 }
208 else if ((BUFFER_SIZE - 1) == i && QUOTE != buf[0])
209 {
210 // Buffer is filled but did not reach the end of path - skip this malformed line
211 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING,
212 (0, "OsclLibraryList::Populate - path too long, skipping line"));
213 #if OSCL_LIBRARY_PERF_LOGGING
214 iLinesRead++;
215 #endif
216 // Advance to end of line
217 while (1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE)
218 {
219 // ignore
220 }
221 }
222 else
223 {
224 // Read in the path, end with terminating character
225 pathBuf[i] = NULL_TERM_CHAR;
226 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_INFO,
227 (0, "OsclLibraryList::Populate - found a match, adding to list: %s",
228 (char*)pathBuf));
229 // Add path to library list
230 iLibList.push_back((char*)pathBuf);
231 #if OSCL_LIBRARY_PERF_LOGGING
232 iLibHit++;
233 iLinesRead++;
234 #endif
235 }
236 }
237 }
238 else
239 {
240 // The UUID from this line does not match aInterfaceId - Advance to end of line
241 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_INFO,
242 (0, "OsclLibraryList::Populate - uuid not a match, skipping line"));
243 #if OSCL_LIBRARY_PERF_LOGGING
244 iLinesRead++;
245 #endif
246 while (1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE)
247 {
248 // ignore
249 }
250 }
251 }
252 }
253 // else continue on to next byte
254 };
255
256 #if OSCL_LIBRARY_PERF_LOGGING
257 // End stats for current config file
258 uint32 difftime;
259 DIFF_TICK(starttime, difftime);
260 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
261 (0, "OsclLibraryList::Populate - Parsing configFile %s ...", aConfigFile.get_cstr()));
262 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
263 (0, " Time taken = %d ticks", difftime));
264 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
265 (0, " Lines read = %d", iLinesRead));
266 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
267 (0, " Libraries found = %d", iLibHit));
268 #endif
269
270 //If there's atleast one library path name loaded in the vector,
271 //it means the parsing is successful for at least a particular OsclUuid
272
273 if (iLibList.size() > 0)
274 {
275 return OsclLibSuccess;
276 }
277 else
278 {
279 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_WARNING,
280 (0, "OsclLibraryList::Populate, Didn't find any DLL for the OsclUuid"));
281 return OsclLibFail;
282 }
283 }
284
Size()285 OSCL_EXPORT_REF uint32 OsclLibraryList::Size()
286 {
287 return iLibList.size();
288 }
289
GetLibraryPathAt(uint32 n)290 OSCL_EXPORT_REF const OSCL_String& OsclLibraryList::GetLibraryPathAt(uint32 n)
291 {
292 return iLibList[n];
293 }
294
295