Initial import of Scalos. To decrease size I have
[AROS-Contrib.git] / scalos / main / ThumbnailCache.c
blobe0a4edfca6e0e87090f4c3fb4e62d7d4bdfd90ef
1 // ThumbnailCache.c
2 // $Date$
3 // $Revision$
5 #include <exec/types.h>
6 #include <graphics/gels.h>
7 #include <graphics/rastport.h>
8 #include <scalos/scalosgfx.h>
10 #define __USE_SYSBASE
12 #include <proto/dos.h>
13 #include <proto/exec.h>
14 #include <proto/graphics.h>
15 #include <proto/utility.h>
16 #include <proto/timer.h>
18 #include "debug.h"
19 #include <proto/scalosgfx.h>
20 #include <proto/scalos.h>
21 #include <proto/sqlite3.h>
23 #include <clib/alib_protos.h>
25 #include <defs.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sqlite3.h>
32 #include "scalos_structures.h"
33 #include "FsAbstraction.h"
34 #include "functions.h"
35 #include "Variables.h"
37 //-----------------------------------------------------------------------
39 #define THUMBNAIL_TABLE_NAME_OLD "ScalosThumbNailTable"
40 #define THUMBNAIL_TABLE_NAME "ScalosThumbNailTableV2"
42 // column inidecs for use with SQLite3Column_***()
43 #define COLUMN_THUMBNAIL_ENDOFLIFE 0
44 #define COLUMN_THUMBNAIL_FILENAME 1
45 #define COLUMN_THUMBNAIL_DEPTH 2
46 #define COLUMN_THUMBNAIL_PREFSWIDTH 3
47 #define COLUMN_THUMBNAIL_PREFSHEIGHT 4
48 #define COLUMN_THUMBNAIL_FILEDATE 5
49 #define COLUMN_THUMBNAIL_IMAGEDATA 6
51 //-----------------------------------------------------------------------
53 struct CachedThumbnail
55 struct DateStamp ctn_FileDate;
56 ULONG ctn_EndOfLife;
57 ULONG ctn_ThumbnailDepth;
58 ULONG ctn_prefWidth;
59 ULONG ctn_prefHeight;
60 UBYTE *ctn_ThumbnailData;
61 size_t ctn_ThumbnailDataSize;
64 //-----------------------------------------------------------------------
66 // local data items
68 //-----------------------------------------------------------------------
70 static int ThumbnailCacheAddEntry(sqlite3 *db, CONST_STRPTR FileName,
71 const struct DateStamp *FileDate, ULONG Depth,
72 void *ThumbnailData, size_t ThumbnailDataSize, ULONG LifetimeDays);
73 static BOOL ThumbnailCacheFindEntry(sqlite3 *db, CONST_STRPTR FileName,
74 struct CachedThumbnail *ctn, ULONG LifetimeDays);
75 static BOOL ThumbnailCacheDeleteEntry(sqlite3 *db, CONST_STRPTR FileName);
76 static BOOL ThumbnailCacheUpdateEndOfLife(sqlite3 *db, CONST_STRPTR FileName, const T_TIMEVAL *tv);
77 static STRPTR ThumbnailCacheGetFileNameFromLock(BPTR fLock);
78 static BOOL ThumbnailCacheIsSameDay(ULONG sec1, ULONG sec2);
79 static int ThumbnailCacheSetMode(sqlite3 *db);
80 static int ThumbnailCacheCreateTable(sqlite3 *db);
81 static void ThumbnailCacheGetEndOfLife(T_TIMEVAL *tv, ULONG LifetimeDays);
82 static void ThumbnailCacheFileExists(sqlite3_context *context, LONG x, sqlite3_value **pVal);
83 static int ThumbnailCacheSetTempDir(sqlite3 *db, CONST_STRPTR DirName);
85 //-----------------------------------------------------------------------
87 BOOL ThumbnailCacheInit(void)
89 sqlite3 *db = NULL;
90 BOOL Success = TRUE;
92 d1(KPrintF("%s/%s/%ld: START SQLite3Base=%08lx\n", __FILE__, __FUNC__, __LINE__, SQLite3Base));
94 do {
95 int rc;
97 if (NULL == SQLite3Base)
98 break;
99 if (strlen(CurrentPrefs.pref_ThumbDatabasePath) < 1)
100 break;
102 rc = SQLite3Open(CurrentPrefs.pref_ThumbDatabasePath, &db);
103 d1(KPrintF("%s/%s/%ld: rc=%ld db=%08lx\n", __FILE__, __FUNC__, __LINE__, rc, db));
104 if (SQLITE_OK != rc)
106 d1(KPrintF("%s/%s/%ld: SQLite3Open() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
107 break;
110 rc = SQLite3BusyTimeout(db, 100);
111 if (SQLITE_OK != rc )
113 d1(KPrintF("%s/%s/%ld: SQLite3BusyTimeout() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
114 break;
117 // try to create our table
118 rc = ThumbnailCacheCreateTable(db);
119 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
120 if (SQLITE_OK != rc )
122 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, SQLite3Errcode(db)));
123 break;
126 rc = ThumbnailCacheSetMode(db);
127 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
128 if (SQLITE_OK != rc )
130 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, SQLite3Errcode(db)));
131 break;
133 } while (0);
135 d1(KPrintF("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
137 if (SQLite3Base)
139 SQLite3Close(db);
142 return Success;
146 void CleanupThumbnailCache(void)
148 d1(KPrintF("%s/%s/%ld: START \n", __FILE__, __FUNC__, __LINE__));
150 // currently No-Op
152 d1(KPrintF("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
155 //-----------------------------------------------------------------------
157 BOOL ThumbnailCacheOpen(APTR *pThumbnailCacheHandle)
159 BOOL Success = FALSE;
160 sqlite3 *db = NULL;
162 d1(KPrintF("%s/%s/%ld: START \n", __FILE__, __FUNC__, __LINE__));
163 *pThumbnailCacheHandle = NULL;
165 do {
166 LONG rc;
168 if (NULL == SQLite3Base)
169 break;
170 if (strlen(CurrentPrefs.pref_ThumbDatabasePath) < 1)
171 break;
173 rc = SQLite3Open(CurrentPrefs.pref_ThumbDatabasePath, &db);
174 d1(KPrintF("%s/%s/%ld: db=%08lx\n", __FILE__, __FUNC__, __LINE__, db));
175 if (SQLITE_OK != rc)
177 d1(KPrintF("%s/%s/%ld: SQLite3Open() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
178 break;
181 rc = ThumbnailCacheCreateTable(db);
182 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
183 if (SQLITE_OK != rc)
185 d1(KPrintF("%s/%s/%ld: ThumbnailCacheCreateTable() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
186 break;
189 rc = ThumbnailCacheSetTempDir(db, CurrentPrefs.pref_SQLiteTempDir);
190 if (SQLITE_OK != rc)
192 d1(KPrintF("%s/%s/%ld: ThumbnailCacheSetTempDir() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
193 break;
196 Success = TRUE;
197 *pThumbnailCacheHandle = (APTR) db;
198 } while (0);
200 if (!Success)
202 ThumbnailCacheClose(pThumbnailCacheHandle);
205 d1(KPrintF("%s/%s/%ld: END Success=%ld\n", __FILE__, __FUNC__, __LINE__, Success));
207 return Success;
211 void ThumbnailCacheClose(APTR *pThumbnailCacheHandle)
213 sqlite3 *db = (sqlite3 *) *pThumbnailCacheHandle;
215 d1(KPrintF("%s/%s/%ld: START db=%08lx\n", __FILE__, __FUNC__, __LINE__, db));
216 if (SQLite3Base && db)
218 SQLite3Close(db);
219 *pThumbnailCacheHandle = NULL;
221 d1(KPrintF("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
224 //-----------------------------------------------------------------------
226 static int ThumbnailCacheAddEntry(sqlite3 *db, CONST_STRPTR FileName,
227 const struct DateStamp *FileDate, ULONG Depth,
228 void *ThumbnailData, size_t ThumbnailDataSize, ULONG LifetimeDays)
230 int rc;
232 d1(KPrintF("%s/%s/%ld: START FileName=<%s> ThumbnailData=%08lx ThumbnailDataSize=%lu\n", \
233 __FILE__, __FUNC__, __LINE__, FileName, ThumbnailData, ThumbnailDataSize));
235 do {
236 T_TIMEVAL tv;
237 sqlite3_stmt *pStmt = NULL;
238 CONST_STRPTR Tail = NULL;
239 static CONST_STRPTR Cmd =
240 "INSERT OR REPLACE INTO " THUMBNAIL_TABLE_NAME " "
241 "VALUES(:endoflife, :path, :depth, "
242 ":prefwidth, :prefheight, :filedate, :thumbnail);";
244 rc = SQLite3PrepareV2(db,
245 Cmd, strlen(Cmd),
246 &pStmt,
247 &Tail);
248 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
249 if (SQLITE_OK != rc)
251 d1(KPrintF("%s/%s/%ld: SQLite3PrepareV2() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
252 break;
255 // endoflife
256 ThumbnailCacheGetEndOfLife(&tv, LifetimeDays);
258 rc = SQLite3BindInt(pStmt, 1, tv.tv_secs);
259 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
260 if (SQLITE_OK != rc)
261 break;
263 // path
264 rc = SQLite3BindText(pStmt, 2,
265 FileName, strlen(FileName),
266 SQLITE_STATIC);
267 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
268 if (SQLITE_OK != rc)
269 break;
271 // depth
272 rc = SQLite3BindInt(pStmt, 3, Depth);
273 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
274 if (SQLITE_OK != rc)
275 break;
277 // prefwidth
278 rc = SQLite3BindInt(pStmt, 4, CurrentPrefs.pref_ThumbNailWidth);
279 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
280 if (SQLITE_OK != rc)
281 break;
283 // prefheight
284 rc = SQLite3BindInt(pStmt, 5, CurrentPrefs.pref_ThumbNailHeight);
285 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
286 if (SQLITE_OK != rc)
287 break;
289 // filedate
290 rc = SQLite3BindBlob(pStmt, 6,
291 (void *) FileDate, sizeof(struct DateStamp),
292 SQLITE_STATIC);
293 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
294 if (SQLITE_OK != rc)
295 break;
297 // thumbnail
298 rc = SQLite3BindBlob(pStmt, 7,
299 ThumbnailData, ThumbnailDataSize,
300 SQLITE_STATIC);
301 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
302 if (SQLITE_OK != rc)
303 break;
305 do {
306 rc = SQLite3Step(pStmt);
307 if (SQLITE_BUSY == rc)
308 Delay(2);
309 } while (SQLITE_ROW == rc || SQLITE_BUSY == rc);
311 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
312 if (SQLITE_DONE != rc)
313 break;
315 rc = SQLite3Finalize(pStmt);
316 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
317 if (SQLITE_OK != rc)
318 break;
319 } while (0);
321 d1(KPrintF("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
323 return TRUE;
326 //-----------------------------------------------------------------------
328 static BOOL ThumbnailCacheFindEntry(sqlite3 *db, CONST_STRPTR FileName,
329 struct CachedThumbnail *ctn, ULONG LifetimeDays)
331 sqlite3_stmt *pStmt = NULL;
332 BOOL Found = FALSE;
333 int rc;
335 ctn->ctn_ThumbnailDepth = 0;
336 ctn->ctn_prefWidth = ctn->ctn_prefHeight = 0;
337 ctn->ctn_ThumbnailDataSize = 0;
338 ctn->ctn_ThumbnailData = NULL;
340 d1(KPrintF("%s/%s/%ld: START FileName=<%s>\n", __FILE__, __FUNC__, __LINE__, FileName));
342 do {
343 const void *BlobData;
344 const struct DateStamp *CachedFileDate;
345 int DataCount;
346 int ColumnBytes;
347 CONST_STRPTR Tail = NULL;
348 static CONST_STRPTR SelectCmd =
349 "SELECT * FROM " THUMBNAIL_TABLE_NAME " "
350 "WHERE IconPath = :path;";
352 rc = SQLite3PrepareV2(db,
353 SelectCmd, strlen(SelectCmd),
354 &pStmt,
355 &Tail);
356 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
357 if (SQLITE_OK != rc)
359 d1(KPrintF("%s/%s/%ld: SQLite3PrepareV2() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
360 break;
363 rc = SQLite3BindText(pStmt, 1,
364 FileName, strlen(FileName),
365 SQLITE_STATIC);
366 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
367 if (SQLITE_OK != rc)
368 break;
370 do {
371 rc = SQLite3Step(pStmt);
372 if (SQLITE_BUSY == rc)
373 Delay(2);
374 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
375 } while (SQLITE_BUSY == rc);
377 // rc is SQLITE_ROW if a record had been found
378 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
379 if (SQLITE_ROW != rc)
380 break;
382 // check if there are rows available
383 DataCount = SQLite3DataCount(pStmt);
384 Found = DataCount > 0;
385 d1(KPrintF("%s/%s/%ld: DataCount=%ld Found=%ld\n", __FILE__, __FUNC__, __LINE__, DataCount, Found));
386 if (!Found)
387 break;
389 // return last access
390 ctn->ctn_EndOfLife = SQLite3ColumnInt(pStmt, COLUMN_THUMBNAIL_ENDOFLIFE);
392 // return stored nominal thumbnail width+height
393 ctn->ctn_prefWidth = SQLite3ColumnInt(pStmt, COLUMN_THUMBNAIL_PREFSWIDTH);
394 ctn->ctn_prefHeight = SQLite3ColumnInt(pStmt, COLUMN_THUMBNAIL_PREFSHEIGHT);
396 // return depth of stored thumbnail
397 ctn->ctn_ThumbnailDepth = SQLite3ColumnInt(pStmt, COLUMN_THUMBNAIL_DEPTH);
399 // return file date
400 ColumnBytes = SQLite3ColumnBytes(pStmt, COLUMN_THUMBNAIL_FILEDATE);
401 d1(KPrintF("%s/%s/%ld: ColumnBytes=%ld\n", __FILE__, __FUNC__, __LINE__, ColumnBytes));
402 if (sizeof(struct DateStamp) != ColumnBytes)
403 break;
404 CachedFileDate = SQLite3ColumnBlob(pStmt, COLUMN_THUMBNAIL_FILEDATE);
405 d1(KPrintF("%s/%s/%ld: CachedFileDate=%08lx\n", __FILE__, __FUNC__, __LINE__, CachedFileDate));
406 if (CachedFileDate)
407 ctn->ctn_FileDate = *CachedFileDate;
408 else
409 break;
411 // return copy of thumbnail image data
412 BlobData = SQLite3ColumnBlob(pStmt, COLUMN_THUMBNAIL_IMAGEDATA);
413 ctn->ctn_ThumbnailDataSize = SQLite3ColumnBytes(pStmt, COLUMN_THUMBNAIL_IMAGEDATA);
415 d1(KPrintF("%s/%s/%ld: ctn_ThumbnailDataSize=%lu\n", __FILE__, __FUNC__, __LINE__, ctn->ctn_ThumbnailDataSize));
417 if (ctn->ctn_ThumbnailDataSize)
419 ctn->ctn_ThumbnailData = ScalosAlloc(ctn->ctn_ThumbnailDataSize);
420 if (ctn->ctn_ThumbnailData)
421 memcpy(ctn->ctn_ThumbnailData, BlobData, ctn->ctn_ThumbnailDataSize);
422 else
423 ctn->ctn_ThumbnailDataSize = 0;
425 } while (0);
427 if (pStmt)
429 /*rc =*/ SQLite3Finalize(pStmt);
430 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
431 (void) rc;
434 d1(KPrintF("%s/%s/%ld: END Found=%ld\n", __FILE__, __FUNC__, __LINE__, Found));
436 return (BOOL) (Found && ctn->ctn_ThumbnailDataSize);
439 //-----------------------------------------------------------------------
441 static BOOL ThumbnailCacheDeleteEntry(sqlite3 *db, CONST_STRPTR FileName)
443 int rc;
444 BOOL Success = FALSE;
446 d1(KPrintF("%s/%s/%ld: FileName=<%s>\n", __FILE__, __FUNC__, __LINE__, FileName));
448 do {
449 sqlite3_stmt *pStmt = NULL;
450 CONST_STRPTR Tail = NULL;
451 static CONST_STRPTR Cmd =
452 "DELETE " THUMBNAIL_TABLE_NAME " "
453 "WHERE IconPath = :path;";
455 rc = SQLite3PrepareV2(db,
456 Cmd, strlen(Cmd),
457 &pStmt,
458 &Tail);
459 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
460 if (SQLITE_OK != rc)
462 d1(KPrintF("%s/%s/%ld: SQLite3PrepareV2() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
463 break;
466 // bind IconPath
467 rc = SQLite3BindText(pStmt, 1,
468 FileName, strlen(FileName),
469 SQLITE_STATIC);
470 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
471 if (SQLITE_OK != rc)
472 break;
474 do {
475 rc = SQLite3Step(pStmt);
476 if (SQLITE_BUSY == rc)
477 Delay(2);
478 } while (SQLITE_ROW == rc || SQLITE_BUSY == rc);
480 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
481 if (SQLITE_DONE != rc)
482 break;
484 rc = SQLite3Finalize(pStmt);
485 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
486 if (SQLITE_OK != rc)
487 break;
489 Success = TRUE;
490 } while (0);
492 d1(KPrintF("%s/%s/%ld: Success=%ld\n", __FILE__, __FUNC__, __LINE__, Success));
494 return Success;
497 //-----------------------------------------------------------------------
499 static BOOL ThumbnailCacheUpdateEndOfLife(sqlite3 *db, CONST_STRPTR FileName, const T_TIMEVAL *tv)
501 int rc;
502 BOOL Success = FALSE;
504 d1(KPrintF("%s/%s/%ld: FileName=<%s>\n", __FILE__, __FUNC__, __LINE__, FileName));
506 do {
507 CONST_STRPTR Tail = NULL;
508 sqlite3_stmt *pStmt = NULL;
509 static CONST_STRPTR Cmd =
510 "UPDATE " THUMBNAIL_TABLE_NAME " "
511 "SET EndOfLife = :endoflife "
512 "WHERE IconPath = :path;";
514 rc = SQLite3PrepareV2(db,
515 Cmd, strlen(Cmd),
516 &pStmt,
517 &Tail);
518 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
519 if (SQLITE_OK != rc)
521 d1(KPrintF("%s/%s/%ld: SQLite3PrepareV2() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
522 break;
525 // bind EndOfLife
526 rc = SQLite3BindInt(pStmt, 1, tv->tv_secs);
527 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
528 if (SQLITE_OK != rc)
529 break;
531 // bind IconPath
532 rc = SQLite3BindText(pStmt, 2,
533 FileName, strlen(FileName),
534 SQLITE_STATIC);
535 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
536 if (SQLITE_OK != rc)
537 break;
539 do {
540 rc = SQLite3Step(pStmt);
541 if (SQLITE_BUSY == rc)
542 Delay(2);
543 } while (SQLITE_ROW == rc || SQLITE_BUSY == rc);
545 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
546 if (SQLITE_DONE != rc)
547 break;
549 rc = SQLite3Finalize(pStmt);
550 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
551 if (SQLITE_OK != rc)
552 break;
554 Success = TRUE;
555 } while (0);
557 d1(KPrintF("%s/%s/%ld: Success=%ld\n", __FILE__, __FUNC__, __LINE__, Success));
559 return Success;
562 //-----------------------------------------------------------------------
564 void ThumbnailCacheAddARGB(BPTR fLock, APTR ThumbnailCacheHandle,
565 const struct ARGBHeader *argbh, ULONG LifetimeDays)
567 sqlite3 *db = (sqlite3 *) ThumbnailCacheHandle;
568 T_ExamineData *fib = NULL;
569 STRPTR FileName = NULL;
570 UBYTE *Buffer = NULL;
572 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
573 debugLock_d1(fLock);
575 do {
576 size_t ImageDataSize;
577 size_t BuffLength;
579 if (NULL == db)
580 break; // fail if thumbnail database is not available
582 if (!ScalosExamineBegin(&fib))
583 break;
585 if (!ScalosExamineLock(fLock, &fib))
586 break;
588 FileName = ThumbnailCacheGetFileNameFromLock(fLock);
589 if (NULL == FileName)
590 break;
592 ImageDataSize = argbh->argb_Width * argbh->argb_Height * sizeof(struct ARGB);
593 BuffLength = sizeof(struct ARGBHeader) + ImageDataSize;
595 Buffer = ScalosAlloc(BuffLength);
596 if (NULL == Buffer)
597 break;
599 memcpy(Buffer, argbh, sizeof(struct ARGBHeader));
600 memcpy(Buffer + sizeof(struct ARGBHeader), argbh->argb_ImageData, ImageDataSize);
602 ThumbnailCacheAddEntry(db, FileName,
603 ScalosExamineGetDate(fib), 24,
604 Buffer, BuffLength, LifetimeDays);
605 } while (0);
607 if (Buffer)
608 ScalosFree(Buffer);
609 if (FileName)
610 FreePathBuffer(FileName);
611 ScalosExamineEnd(&fib);
613 d1(KPrintF("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
616 //-----------------------------------------------------------------------
618 void ThumbnailCacheAddRemapped(BPTR fLock, APTR ThumbnailCacheHandle,
619 const struct ScalosBitMapAndColor *sac, ULONG LifetimeDays)
621 sqlite3 *db = (sqlite3 *) ThumbnailCacheHandle;
622 T_ExamineData *fib = NULL;
623 STRPTR FileName = NULL;
624 UBYTE *Buffer = NULL;
625 struct RastPort TempRp;
627 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
629 memset(&TempRp, 0, sizeof(TempRp));
631 do {
632 size_t BuffLength;
633 size_t PixelArrayLength;
634 size_t ColorTableLength;
635 struct RastPort SrcRp;
636 ULONG *ColorTable;
638 if (NULL == db)
639 break; // fail if thumbnail database is not available
641 if (!ScalosExamineBegin(&fib))
642 break;
644 if (!ScalosExamineLock(fLock, &fib))
645 break;
647 FileName = ThumbnailCacheGetFileNameFromLock(fLock);
648 if (NULL == FileName)
649 break;
651 ColorTableLength = 3 * sizeof(ULONG) * sac->sac_NumColors;
652 PixelArrayLength = PIXELARRAY8_BUFFERSIZE(sac->sac_Width, sac->sac_Height);
653 BuffLength = sizeof(struct ScalosBitMapAndColor)
654 + PixelArrayLength + ColorTableLength;
656 Buffer = ScalosAlloc(BuffLength);
657 if (NULL == Buffer)
658 break;
660 InitRastPort(&SrcRp);
661 SrcRp.BitMap = (struct BitMap *) sac->sac_BitMap;
663 memcpy(Buffer, sac, sizeof(struct ScalosBitMapAndColor));
665 InitRastPort(&TempRp);
666 TempRp.BitMap = AllocBitMap(TEMPRP_WIDTH(sac->sac_Width), 1, 8, 0, NULL);
667 if (NULL == TempRp.BitMap)
668 break;
670 // Blit BitMap data to buffer
671 ReadPixelArray8(&SrcRp,
672 0, 0,
673 sac->sac_Width - 1, sac->sac_Height - 1,
674 Buffer + sizeof(struct ScalosBitMapAndColor),
675 &TempRp);
677 // Copy ColorTable to buffer
678 ColorTable = (ULONG *) (Buffer + sizeof(struct ScalosBitMapAndColor) + PixelArrayLength);
679 memcpy(ColorTable, sac->sac_ColorTable, ColorTableLength);
681 ThumbnailCacheAddEntry(db, FileName,
682 ScalosExamineGetDate(fib), sac->sac_Depth,
683 Buffer, BuffLength, LifetimeDays);
684 } while (0);
686 if (TempRp.BitMap)
688 FreeBitMap(TempRp.BitMap);
689 TempRp.BitMap = NULL;
691 if (Buffer)
692 ScalosFree(Buffer);
693 if (FileName)
694 FreePathBuffer(FileName);
695 ScalosExamineEnd(&fib);
697 d1(KPrintF("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
700 //-----------------------------------------------------------------------
702 BOOL ThumbnailCacheFindARGB(BPTR fLock, APTR ThumbnailCacheHandle,
703 struct ARGBHeader *argbh, ULONG LifetimeDays)
705 sqlite3 *db = (sqlite3 *) ThumbnailCacheHandle;
706 T_ExamineData *fib = NULL;
707 STRPTR FileName = NULL;
708 struct CachedThumbnail ctn;
709 BOOL Found = FALSE;
710 BOOL ShouldDeleteEntry = FALSE;
712 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
713 debugLock_d1(fLock);
715 memset(&ctn, 0, sizeof(ctn));
717 do {
718 T_TIMEVAL tv;
719 size_t ImageDataSize;
721 if (NULL == db)
722 break; // fail if thumbnail database is not available
724 FileName = ThumbnailCacheGetFileNameFromLock(fLock);
725 if (NULL == FileName)
726 break;
728 if (!ScalosExamineBegin(&fib))
729 break;
731 if (!ScalosExamineLock(fLock, &fib))
732 break;
734 if (!ThumbnailCacheFindEntry(db, FileName, &ctn, LifetimeDays))
735 break;
737 if (0 == ctn.ctn_ThumbnailDataSize || NULL == ctn.ctn_ThumbnailData)
738 break;
740 // check if we have an ARGB thumbnail here
741 d1(KPrintF("%s/%s/%ld: ThumbnailDepth=%lu\n", __FILE__, __FUNC__, __LINE__, ctn.ctn_ThumbnailDepth));
742 if (ctn.ctn_ThumbnailDepth != 24)
743 break;
745 if (ctn.ctn_prefWidth != CurrentPrefs.pref_ThumbNailWidth
746 || ctn.ctn_prefHeight != CurrentPrefs.pref_ThumbNailHeight)
748 // Cached thumbnail size doesn't match current settings
749 // mark it for deletion
750 ShouldDeleteEntry = TRUE;
751 d1(KPrintF("%s/%s/%ld: width/height mismatch w=%lu h=%lu\n", \
752 __FILE__, __FUNC__, __LINE__, ctn.ctn_prefWidth, ctn.ctn_prefHeight));
753 break;
756 if (0 != CompareDates(&ctn.ctn_FileDate, ScalosExamineGetDate(fib)))
758 // cache entry is outdated
759 // mark it for deletion
760 d1(KPrintF("%s/%s/%ld: FileDate mismatch\n", __FILE__, __FUNC__, __LINE__));
761 ShouldDeleteEntry = TRUE;
762 break;
765 // copy ARGB header
766 memcpy(argbh, ctn.ctn_ThumbnailData, sizeof(struct ARGBHeader));
768 // allocate ARGB image data
769 argbh->argb_ImageData = ScalosGfxCreateARGB(argbh->argb_Width, argbh->argb_Height, NULL);
770 if (NULL == argbh->argb_ImageData)
771 break;
773 ImageDataSize = argbh->argb_Width * argbh->argb_Height * sizeof(struct ARGB);
775 // copy ARGB data
776 memcpy(argbh->argb_ImageData, ctn.ctn_ThumbnailData + sizeof(struct ARGBHeader), ImageDataSize);
778 // Check if database entry access date should be updated
779 // Since updating takes time, entries are updated no more than once a day.
780 ThumbnailCacheGetEndOfLife(&tv, LifetimeDays);
782 d1(KPrintF("%s/%s/%ld: tv_secs=%lu ctn_EndOfLife=%lu\n", \
783 __FILE__, __FUNC__, __LINE__, tv.tv_secs, ctn.ctn_EndOfLife));
785 if (!ThumbnailCacheIsSameDay(tv.tv_secs, ctn.ctn_EndOfLife))
786 ThumbnailCacheUpdateEndOfLife(db, FileName, &tv);
788 Found = TRUE;
789 } while (0);
791 if (FileName && ShouldDeleteEntry)
792 ThumbnailCacheDeleteEntry(db, FileName);
794 if (ctn.ctn_ThumbnailData)
795 ScalosFree(ctn.ctn_ThumbnailData);
796 if (FileName)
797 FreePathBuffer(FileName);
798 ScalosExamineEnd(&fib);
800 d1(KPrintF("%s/%s/%ld: END Found=%ld\n", __FILE__, __FUNC__, __LINE__, Found));
802 return Found;
805 //-----------------------------------------------------------------------
807 struct ScalosBitMapAndColor *ThumbnailCacheFindRemapped(BPTR fLock,
808 APTR ThumbnailCacheHandle, ULONG LifetimeDays)
810 sqlite3 *db = (sqlite3 *) ThumbnailCacheHandle;
811 struct RastPort TempRp;
812 T_ExamineData *fib = NULL;
813 STRPTR FileName = NULL;
814 BOOL Found = FALSE;
815 BOOL ShouldDeleteEntry = FALSE;
816 struct CachedThumbnail ctn;
817 struct ScalosBitMapAndColor *newsac = NULL;
819 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
820 debugLock_d1(fLock);
822 memset(&TempRp, 0, sizeof(TempRp));
823 memset(&ctn, 0, sizeof(ctn));
825 do {
826 T_TIMEVAL tv;
827 size_t ColorTableLength;
828 size_t PixelArrayLength;
829 const UBYTE *PixelArray;
830 const ULONG *ColorTable;
831 struct RastPort DestRp;
832 struct ScalosBitMapAndColor sac;
834 memset(&sac, 0, sizeof(struct ScalosBitMapAndColor));
836 if (NULL == db)
837 break; // fail if thumbnail database is not available
839 InitRastPort(&DestRp);
841 FileName = ThumbnailCacheGetFileNameFromLock(fLock);
842 if (NULL == FileName)
843 break;
845 if (!ScalosExamineBegin(&fib))
846 break;
848 if (!ScalosExamineLock(fLock, &fib))
849 break;
851 if (!ThumbnailCacheFindEntry(db, FileName, &ctn, LifetimeDays))
852 break;
854 if (0 == ctn.ctn_ThumbnailDataSize || NULL == ctn.ctn_ThumbnailData)
855 break;
857 // check if we have a SAC thumbnail here
858 d1(KPrintF("%s/%s/%ld: ThumbnailDepth=%lu\n", __FILE__, __FUNC__, __LINE__, ctn.ctn_ThumbnailDepth));
859 if (ctn.ctn_ThumbnailDepth > 8)
860 break;
862 if (ctn.ctn_prefWidth != CurrentPrefs.pref_ThumbNailWidth
863 || ctn.ctn_prefHeight != CurrentPrefs.pref_ThumbNailHeight)
865 // Cached thumbnail size doesn't match current settings
866 // mark it for deletion
867 ShouldDeleteEntry = TRUE;
868 d1(KPrintF("%s/%s/%ld: width/height mismatch w=%lu h=%lu\n", \
869 __FILE__, __FUNC__, __LINE__, ctn.ctn_prefWidth, ctn.ctn_prefHeight));
870 break;
873 if (0 != CompareDates(&ctn.ctn_FileDate, ScalosExamineGetDate(fib)))
875 // cache entry is outdated
876 // mark it for deletion
877 d1(KPrintF("%s/%s/%ld: FileDate mismatch\n", __FILE__, __FUNC__, __LINE__));
878 ShouldDeleteEntry = TRUE;
879 break;
882 // copy ScalosBitMapAndColor
883 memcpy(&sac, ctn.ctn_ThumbnailData, sizeof(struct ScalosBitMapAndColor));
885 d1(KPrintF("%s/%s/%ld: Width=%ld Height=%ld Depth=%ld TransparentColor=%ld NumColors=%ld\n", \
886 __FILE__, __FUNC__, __LINE__, sac.sac_Width, sac.sac_Height, sac.sac_Depth, \
887 sac.sac_TransparentColor, sac.sac_NumColors));
889 ColorTableLength = 3 * sizeof(ULONG) * sac.sac_NumColors;
890 PixelArrayLength = PIXELARRAY8_BUFFERSIZE(sac.sac_Width, sac.sac_Height);
892 PixelArray = ctn.ctn_ThumbnailData + sizeof(struct ScalosBitMapAndColor);
893 ColorTable = (ULONG *) (ctn.ctn_ThumbnailData + sizeof(struct ScalosBitMapAndColor) + PixelArrayLength);
895 d1(KPrintF("%s/%s/%ld: PixelArray=%08lx ColorTable=%08lx\n", \
896 __FILE__, __FUNC__, __LINE__, PixelArray, ColorTable));
897 d1(KPrintF("%s/%s/%ld: PixelArrayLength=%lu ColorTableLength=%lu\n", \
898 __FILE__, __FUNC__, __LINE__, PixelArrayLength, ColorTableLength));
900 newsac = ScalosGfxCreateSAC(sac.sac_Width, sac.sac_Height, sac.sac_Depth, NULL, NULL);
901 d1(KPrintF("%s/%s/%ld: newsac=%08lx\n", __FILE__, __FUNC__, __LINE__, newsac));
902 if (NULL == newsac)
903 break;
905 newsac->sac_TransparentColor = sac.sac_TransparentColor;
907 // Copy data into colortable
908 memcpy(newsac->sac_ColorTable, ColorTable, ColorTableLength);
910 // Initialize temporary RastPort
911 InitRastPort(&TempRp);
912 TempRp.BitMap = AllocBitMap(TEMPRP_WIDTH(newsac->sac_Width), 1, 8, 0, NULL);
913 if (NULL == TempRp.BitMap)
914 break;
916 d1(KPrintF("%s/%s/%ld: TempRp.BitMap=%08lx\n", __FILE__, __FUNC__, __LINE__, TempRp.BitMap));
918 // Blit image data to BitMap
919 DestRp.BitMap = newsac->sac_BitMap;
920 WritePixelArray8(&DestRp,
921 0, 0,
922 newsac->sac_Width - 1, newsac->sac_Height - 1,
923 (UBYTE *) PixelArray,
924 &TempRp);
926 // Check if database entry access date should be updated
927 // Since updating takes time, entries are updated only once a day.
928 ThumbnailCacheGetEndOfLife(&tv, LifetimeDays);
930 d1(KPrintF("%s/%s/%ld: tv_secs=%lu ctn_EndOfLife=%lu\n", \
931 __FILE__, __FUNC__, __LINE__, tv.tv_secs, ctn.ctn_EndOfLife));
933 if (!ThumbnailCacheIsSameDay(tv.tv_secs, ctn.ctn_EndOfLife))
934 ThumbnailCacheUpdateEndOfLife(db, FileName, &tv);
936 Found = TRUE;
937 WaitBlit();
938 } while (0);
940 if (FileName && ShouldDeleteEntry)
941 ThumbnailCacheDeleteEntry(db, FileName);
943 if (TempRp.BitMap)
944 FreeBitMap(TempRp.BitMap);
945 if (ctn.ctn_ThumbnailData)
946 ScalosFree(ctn.ctn_ThumbnailData);
947 if (FileName)
948 FreePathBuffer(FileName);
949 ScalosExamineEnd(&fib);
951 if (!Found)
953 // cleanup allocated newsac if not found
954 ScalosGfxFreeSAC(newsac);
955 newsac = NULL;
958 d1(KPrintF("%s/%s/%ld: END Found=%ld\n", __FILE__, __FUNC__, __LINE__, Found));
960 return newsac;
963 //-----------------------------------------------------------------------
965 static STRPTR ThumbnailCacheGetFileNameFromLock(BPTR fLock)
967 STRPTR FileName;
969 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
970 debugLock_d1(fLock);
972 FileName = AllocPathBuffer();
973 if (FileName)
975 if (!NameFromLock(fLock, FileName, Max_PathLen))
977 FreePathBuffer(FileName);
978 FileName = NULL;
982 d1(KPrintF("%s/%s/%ld: END FileName=%08lx\n", __FILE__, __FUNC__, __LINE__, FileName));
984 return FileName;
987 //-----------------------------------------------------------------------
989 static BOOL ThumbnailCacheIsSameDay(ULONG sec1, ULONG sec2)
991 return (BOOL) (abs(sec1 - sec2) <= 60 * 60 * 24);
994 //-----------------------------------------------------------------------
996 BOOL ThumbnailCacheRemoveEntry(BPTR DirLock, CONST_STRPTR FileName)
998 APTR ThumbnailCacheHandle;
999 BOOL Success = FALSE;
1000 STRPTR FullPath;
1002 d1(KPrintF("%s/%s/%ld: START FileName=<%s>\n", __FILE__, __FUNC__, __LINE__, FileName));
1004 do {
1005 sqlite3 *db;
1007 FullPath = AllocPathBuffer();
1008 if (NULL == FullPath)
1009 break;
1011 if (!ThumbnailCacheOpen(&ThumbnailCacheHandle))
1012 break;
1014 db = (sqlite3 *) ThumbnailCacheHandle;
1015 if (NULL == db)
1016 break;
1018 if (!NameFromLock(DirLock, FullPath, Max_PathLen))
1019 break;
1021 if (!AddPart(FullPath, FileName, Max_PathLen))
1022 break;
1024 Success = ThumbnailCacheDeleteEntry(db, FullPath);
1025 } while (0);
1027 if (FullPath)
1028 FreePathBuffer(FullPath);
1030 ThumbnailCacheClose(&ThumbnailCacheHandle);
1032 d1(KPrintF("%s/%s/%ld: END Success=%ld\n", __FILE__, __FUNC__, __LINE__, Success));
1034 return Success;
1037 //-----------------------------------------------------------------------
1039 // Cleanup thumbnail cache -- remove all entries that
1040 // have not been accessed for a defined time.
1042 BOOL ThumbnailCacheCleanup(APTR ThumbnailCacheHandle)
1044 sqlite3 *db = (sqlite3 *) ThumbnailCacheHandle;
1045 sqlite3_stmt *pStmt = NULL;
1046 int rc = SQLITE_DONE;
1048 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
1050 do {
1051 T_TIMEVAL tv;
1052 CONST_STRPTR Tail = NULL;
1053 LONG Changes;
1054 static CONST_STRPTR SelectCmd =
1055 "DELETE FROM " THUMBNAIL_TABLE_NAME " "
1056 "WHERE EndOfLife < :accessdate OR NOT FILEXISTS(IconPath);";
1058 if (NULL == db)
1059 break; // fail if thumbnail database is not available
1061 d1(KPrintF("%s/%s/%ld: db=%08lx\n", __FILE__, __FUNC__, __LINE__, db));
1063 rc = SQLite3ExtendedResultCodes(db, TRUE);
1064 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1065 if (SQLITE_OK != rc)
1067 d1(KPrintF("%s/%s/%ld: SQLite3ExtendedResultCodes() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
1068 break;
1071 // Delete old V1 table if exists
1072 /* rc = */SQLite3Exec(db,
1073 "DROP TABLE IF EXISTS " THUMBNAIL_TABLE_NAME_OLD ";",
1074 NULL,
1075 NULL,
1076 NULL);
1077 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1079 GetSysTime(&tv);
1081 // Register custom "FILEEXISTS" function
1082 rc = SQLite3CreateFunction(db,
1083 "FILEXISTS",
1085 SQLITE_ANY,
1086 NULL,
1087 ThumbnailCacheFileExists,
1088 NULL,
1089 NULL);
1090 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1091 if (SQLITE_OK != rc)
1093 d1(KPrintF("%s/%s/%ld: SQLite3CreateFunction() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
1094 break;
1097 rc = SQLite3PrepareV2(db,
1098 SelectCmd, strlen(SelectCmd),
1099 &pStmt,
1100 &Tail);
1101 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1102 if (SQLITE_OK != rc)
1104 d1(KPrintF("%s/%s/%ld: SQLite3PrepareV2() failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
1105 break;
1108 rc = SQLite3BindInt(pStmt, 1, tv.tv_secs);
1109 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1110 if (SQLITE_OK != rc)
1111 break;
1113 do {
1114 rc = SQLite3Step(pStmt);
1115 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1116 if (SQLITE_BUSY == rc)
1117 Delay(2);
1118 } while (SQLITE_ROW == rc || SQLITE_BUSY == rc);
1120 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1121 if (SQLITE_DONE != rc)
1122 break;
1124 rc = SQLite3Finalize(pStmt);
1125 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1126 if (SQLITE_OK != rc)
1127 break;
1129 pStmt = NULL;
1131 // Check how many records have been deleted
1132 Changes = SQLite3Changes(db);
1133 d1(KPrintF("%s/%s/%ld: Changes=%ld\n", __FILE__, __FUNC__, __LINE__, Changes));
1135 if (Changes < 1)
1136 break;
1138 // If records have been deleted, compress the database now
1140 rc = SQLite3Exec(db,
1141 "VACUUM;",
1142 NULL,
1143 NULL,
1144 NULL);
1145 if (SQLITE_DONE != rc && SQLITE_OK != rc)
1147 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1148 d1(KPrintF("%s/%s/%ld: VACUUM failed: <%s>\n", __FILE__, __FUNC__, __LINE__, SQLite3Errmsg(db)));
1149 break;
1151 } while (0);
1153 if (pStmt)
1155 /*rc =*/ SQLite3Finalize(pStmt);
1156 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1157 (void) rc;
1160 d1(KPrintF("%s/%s/%ld: END rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1162 return (BOOL) (SQLITE_DONE == rc || SQLITE_OK == rc);
1165 //-----------------------------------------------------------------------
1167 static int ThumbnailCacheSetMode(sqlite3 *db)
1169 int rc;
1171 d1(KPrintF("%s/%s/%ld: START db=%08lx\n", __FILE__, __FUNC__, __LINE__, db));
1173 do {
1174 rc = SQLite3Exec(db,
1175 "PRAGMA journal_mode=wal;",
1176 NULL,
1177 NULL,
1178 NULL);
1179 d1(KPrintF("%s/%s/%ld: PRAGMA journal_mode=wal returns rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1180 if (SQLITE_DONE != rc && SQLITE_OK != rc)
1181 break;
1183 rc = SQLite3EnableSharedCache(TRUE);
1184 d1(KPrintF("%s/%s/%ld: SQLite3EnableSharedCache() returns rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1185 if (SQLITE_DONE != rc && SQLITE_OK != rc)
1186 break;
1188 } while (0);
1190 d1(KPrintF("%s/%s/%ld: END rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1192 return rc;
1196 //-----------------------------------------------------------------------
1198 static int ThumbnailCacheCreateTable(sqlite3 *db)
1200 int rc;
1202 d1(KPrintF("%s/%s/%ld: START db=%08lx\n", __FILE__, __FUNC__, __LINE__, db));
1204 do {
1205 rc = SQLite3Exec(db,
1206 "CREATE TABLE IF NOT EXISTS " THUMBNAIL_TABLE_NAME "("
1207 "EndOfLife integer DEFAULT CURRENT_DATESTAMP,"
1208 "IconPath text PRIMARY KEY UNIQUE ON CONFLICT REPLACE,"
1209 "ThumbnailDepth integer,"
1210 "PrefThumbnailWidth integer,"
1211 "PrefThumbnailHeight integer,"
1212 "FileDate integer,"
1213 "Thumbnail blob"
1214 ");",
1215 NULL,
1216 NULL,
1217 NULL);
1218 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1219 if (SQLITE_DONE != rc && SQLITE_OK != rc)
1220 break;
1222 rc = SQLite3Exec(db,
1223 "CREATE INDEX IF NOT EXISTS EolIndex "
1224 "ON " THUMBNAIL_TABLE_NAME "(EndOfLife);",
1225 NULL,
1226 NULL,
1227 NULL);
1228 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1229 if (SQLITE_DONE != rc && SQLITE_OK != rc)
1230 break;
1232 rc = SQLite3Exec(db,
1233 "CREATE UNIQUE INDEX IF NOT EXISTS PathIndex "
1234 "ON " THUMBNAIL_TABLE_NAME "(IconPath);",
1235 NULL,
1236 NULL,
1237 NULL);
1238 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1239 if (SQLITE_DONE != rc && SQLITE_OK != rc)
1240 break;
1241 } while (0);
1243 d1(KPrintF("%s/%s/%ld: END rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1245 return rc;
1248 //-----------------------------------------------------------------------
1250 BOOL ThumbnailCacheBegin(APTR ThumbnailCacheHandle)
1252 #if 0
1253 sqlite3 *db = (sqlite3 *) ThumbnailCacheHandle;
1254 int rc = SQLITE_DONE;
1256 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
1257 if (SQLite3Base && db)
1259 rc = SQLite3Exec(db,
1260 "BEGIN DEFERRED TRANSACTION;",
1261 NULL,
1262 NULL,
1263 NULL);
1265 d1(KPrintF("%s/%s/%ld: END rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1267 return (BOOL) (SQLITE_DONE == rc || SQLITE_OK == rc);
1268 #else
1269 return TRUE;
1270 #endif
1273 //-----------------------------------------------------------------------
1275 BOOL ThumbnailCacheFinish(APTR ThumbnailCacheHandle)
1277 #if 0
1278 sqlite3 *db = (sqlite3 *) ThumbnailCacheHandle;
1279 int rc = SQLITE_DONE;
1281 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
1283 if (SQLite3Base && db)
1285 rc = SQLite3Exec(db,
1286 "END TRANSACTION;",
1287 NULL,
1288 NULL,
1289 NULL);
1290 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1293 d1(KPrintF("%s/%s/%ld: END rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1295 return (BOOL) (SQLITE_DONE == rc || SQLITE_OK == rc);
1296 #else
1297 return TRUE;
1298 #endif
1301 //-----------------------------------------------------------------------
1303 static void ThumbnailCacheGetEndOfLife(T_TIMEVAL *tv, ULONG LifetimeDays)
1305 GetSysTime(tv);
1306 if (LifetimeDays)
1307 tv->tv_secs += 24 * 60 * 60 * LifetimeDays;
1308 else
1309 tv->tv_secs = ULONG_MAX; // forever
1312 //-----------------------------------------------------------------------
1314 static void ThumbnailCacheFileExists(sqlite3_context *context, LONG x, sqlite3_value **pVal)
1316 BOOL fileExists = FALSE;
1317 CONST_STRPTR Path;
1319 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
1321 (void) x;
1323 Path = SQLite3ValueText(*pVal);
1324 d1(KPrintF("%s/%s/%ld: Path=<%s>\n", __FILE__, __FUNC__, __LINE__, Path ? Path : (CONST_STRPTR) ""));
1326 if (Path && strlen(Path) > 0)
1328 BPTR fLock;
1330 fLock = Lock(Path, ACCESS_READ);
1331 d1(KPrintF("%s/%s/%ld: fLock=%08lx\n", __FILE__, __FUNC__, __LINE__, fLock));
1332 if (fLock)
1334 fileExists = TRUE;
1335 UnLock(fLock);
1337 else
1339 LONG ErrCode = IoErr();
1341 if (ERROR_DEVICE_NOT_MOUNTED == ErrCode)
1342 fileExists = TRUE;
1346 SQLite3ResultInt(context, fileExists);
1348 d1(KPrintF("%s/%s/%ld: END fileExists=%ld\n", __FILE__, __FUNC__, __LINE__, fileExists));
1351 //-----------------------------------------------------------------------
1353 static int ThumbnailCacheSetTempDir(sqlite3 *db, CONST_STRPTR DirName)
1355 STRPTR CmdStr;
1356 int rc;
1358 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
1360 do {
1361 size_t Length;
1362 static CONST_STRPTR Cmd =
1363 "PRAGMA temp_store_directory = \"%s\";";
1365 Length = 1 + strlen(Cmd) + strlen(DirName);
1367 CmdStr = ScalosAlloc(Length);
1368 if (NULL == CmdStr)
1370 rc = SQLITE_NOMEM;
1371 break;
1374 snprintf(CmdStr, Length, Cmd, DirName);
1376 rc = SQLite3Exec(db,
1377 CmdStr,
1378 NULL,
1379 NULL,
1380 NULL);
1381 d1(KPrintF("%s/%s/%ld: rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1382 } while (0);
1384 if (CmdStr)
1385 ScalosFree(CmdStr);
1387 d1(KPrintF("%s/%s/%ld: END rc=%ld\n", __FILE__, __FUNC__, __LINE__, rc));
1389 return rc;
1392 //-----------------------------------------------------------------------