src/lib/cache.c
changeset 1 f3cde3db1fef
parent 0 cff7fac35cc2
child 2 05de54150a4c
equal deleted inserted replaced
0:cff7fac35cc2 1:f3cde3db1fef
     1 #include "cache.h"
     1 #include "cache.h"
     2 
     2 
     3 static int pt_cache_new (struct pt_cache **cache_ptr)
     3 #include <stdlib.h>
       
     4 #include <unistd.h>
       
     5 #include <sys/types.h>
       
     6 #include <sys/stat.h>
       
     7 #include <fcntl.h>
       
     8 #include <sys/mman.h>
       
     9 
       
    10 
       
    11 
       
    12 static int pt_cache_new (struct pt_cache **cache_ptr, const char *path)
     4 {
    13 {
     5     struct pt_cache *cache;
    14     struct pt_cache *cache;
     6 
    15 
       
    16     // alloc
     7     if ((cache = calloc(1, sizeof(*cache))) == NULL)
    17     if ((cache = calloc(1, sizeof(*cache))) == NULL)
     8         return -1;
    18         return -1;
     9 
    19 
       
    20     if ((cache->path = strdup(path)) == NULL)
       
    21         goto error;
       
    22 
       
    23     // init
       
    24     cache->fd = -1;
       
    25 
    10     // ok
    26     // ok
    11     *cache_ptr = cache;
    27     *cache_ptr = cache;
    12 
    28 
    13     return 0;
    29     return 0;
    14 }
    30 
    15 
    31 error:
    16 int pt_cache_open (struct pt_cache **cache_ptr, struct pt_image *img, int mode)
    32     // cleanup
       
    33     if (cache)
       
    34         pt_cache_destroy(cache);
       
    35 
       
    36     return -1;
       
    37 }
       
    38 
       
    39 int pt_cache_open (struct pt_cache **cache_ptr, const char *path, int mode)
    17 {
    40 {
    18     struct pt_cache *cache;
    41     struct pt_cache *cache;
    19     
    42     
    20     // alloc
    43     // alloc
    21     if (pt_cache_new(&cache))
    44     if (pt_cache_new(&cache, path))
    22         return -1;
    45         return -1;
    23 
       
    24     
    46     
    25 }
    47     // ok
    26 
    48     *cache_ptr = cache;
    27 bool pt_cache_fresh (struct pt_cache *cache)
    49 
       
    50     return 0;
       
    51 }
       
    52 
       
    53 int pt_cache_stale (struct pt_cache *cache, const char *orig_path)
    28 {
    54 {
    29     // TODO: stat + mtime
    55     // TODO: stat + mtime
    30     return false;
    56     return false;
    31 }
    57 }
    32 
    58 
    33 /**
    59 /**
       
    60  * Abort any incomplete open operation, cleaning up
       
    61  */
       
    62 static void pt_cache_abort (struct pt_cache *cache)
       
    63 {
       
    64     if (cache->mmap != NULL) {
       
    65         munmap(cache->mmap, cache->size);
       
    66 
       
    67         cache->mmap = NULL;
       
    68     }
       
    69 
       
    70     if (cache->fd >= 0) {
       
    71         close(cache->fd);
       
    72 
       
    73         cache->fd = -1;
       
    74     }
       
    75 }
       
    76 
       
    77 /**
       
    78  * Open the cache file as an fd.
       
    79  *
       
    80  * XXX: needs locking
       
    81  */
       
    82 static int pt_cache_open_fd (struct pt_cache *cache, int *fd_ptr)
       
    83 {
       
    84     int fd;
       
    85     int flags = 0;
       
    86 
       
    87     // determine open flags
       
    88     // XXX: O_RDONLY | O_WRONLY == O_RDWR?
       
    89     if (cache->mode & PT_IMG_READ)
       
    90         flags |= O_RDONLY;
       
    91 
       
    92     if (cache->mode & PT_IMG_WRITE)
       
    93         flags |= (O_WRONLY | O_CREAT);
       
    94 
       
    95     // actual open()
       
    96     if ((fd = open(cache->path, flags)) < 0)
       
    97         return -1;
       
    98 
       
    99     // ok
       
   100     *fd_ptr = fd;
       
   101 
       
   102     return 0;
       
   103 }
       
   104 
       
   105 /**
       
   106  * Mmap the opened cache file from offset PT_CACHE_PAGE, using the calculated size stored in cache->size
       
   107  */
       
   108 static int pt_cache_open_mmap (struct pt_cache *cache, void **addr_ptr)
       
   109 {
       
   110     int prot = 0;
       
   111     void *addr;
       
   112 
       
   113     // determine prot
       
   114     if (cache->mode & PT_IMG_READ)
       
   115         prot |= PROT_READ;
       
   116 
       
   117     if (cache->mode & PT_IMG_WRITE)
       
   118         prot |= PROT_WRITE;
       
   119 
       
   120     // perform mmap() from second page on
       
   121     if ((addr = mmap(NULL, cache->size, prot, MAP_SHARED, cache->fd, PT_CACHE_PAGE)) == MAP_FAILED)
       
   122         return -1;
       
   123 
       
   124     // ok
       
   125     *addr_ptr = addr;
       
   126 
       
   127     return 0;
       
   128 }
       
   129 
       
   130 /**
       
   131  * Write out the cache header into the opened file
       
   132  */
       
   133 static int pt_cache_write_header (struct pt_cache *cache, const struct pt_cache_header *header)
       
   134 {
       
   135     size_t len = sizeof(*header);
       
   136     const char *buf = (const char *) header;
       
   137 
       
   138     // seek to start
       
   139     if (lseek(cache->fd, 0, SEEK_SET) != 0)
       
   140         return -1;
       
   141 
       
   142     // write out full header
       
   143     while (len) {
       
   144         ssize_t ret;
       
   145         
       
   146         // try and write out the header
       
   147         if ((ret = write(cache->fd, buf, len)) < 0)
       
   148             return -1;
       
   149 
       
   150         // update offset
       
   151         buf += ret;
       
   152         len -= ret;
       
   153     }
       
   154 
       
   155     // done
       
   156     return 0;
       
   157 }
       
   158 
       
   159 /**
    34  * Create a new cache file, open it, and write out the header.
   160  * Create a new cache file, open it, and write out the header.
    35  */
   161  */
    36 static int pt_cache_create (struct pt_cache *cache, struct pt_cache_header *header)
   162 static int pt_cache_open_create (struct pt_cache *cache, struct pt_cache_header *header)
    37 {
   163 {
       
   164     // open
       
   165     if (pt_cache_open_fd(cache, &cache->fd))
       
   166         return -1;
       
   167 
       
   168     // calculate data size
       
   169     cache->size = sizeof(*header) + header->height * header->row_bytes;
       
   170 
       
   171     // grow file
       
   172     if (ftruncate(cache->fd, PT_CACHE_PAGE + cache->size) < 0)
       
   173         goto error;
       
   174 
       
   175     // open mmap
       
   176     if (pt_cache_open_mmap(cache, (void **) &cache->mmap))
       
   177         goto error;
       
   178 
       
   179     // write header
       
   180     if (pt_cache_write_header(cache, header))
       
   181         goto error;
       
   182 
       
   183     // done
       
   184     return 0;
       
   185 
       
   186 error:
       
   187     // cleanup
       
   188     pt_cache_abort(cache);
       
   189 
       
   190     return -1;
       
   191 }
       
   192 
       
   193 int pt_cache_update_png (struct pt_cache *cache, png_structp png, png_infop info)
       
   194 {
       
   195     struct pt_cache_header header;
    38     
   196     
    39 }
   197     // XXX: check cache_mode
    40 
   198     // XXX: check image doesn't use any options we don't handle
    41 int pt_cache_update_png (struct pt_cache *cache, png_structp png, png_infop info)
       
    42 {
       
    43     struct pt_cache_header header;
       
    44 
   199 
    45     memset(&header, 0, sizeof(header));
   200     memset(&header, 0, sizeof(header));
    46 
   201 
    47     // fill in basic info
   202     // fill in basic info
    48     header->width = png_get_image_width(png, info);
   203     header.width = png_get_image_width(png, info);
    49     header->height = png_get_image_height(png, info);
   204     header.height = png_get_image_height(png, info);
    50     header->bit_depth = png_get_bit_depth(png, info);
   205     header.bit_depth = png_get_bit_depth(png, info);
    51     header->color_type = png_get_color_type(png, info);
   206     header.color_type = png_get_color_type(png, info);
    52 
   207 
    53     // fill in other info
   208     // fill in other info
    54     header->row_bytes = png_get_rowbytes(png, info);
   209     header.row_bytes = png_get_rowbytes(png, info);
    55 }
   210 
       
   211     // create and write out header
       
   212     if (pt_cache_open_create(cache, &header))
       
   213         return -1;
       
   214 
       
   215     // XXX: pallette etc.
       
   216 
       
   217     // write out raw image data a row at a time
       
   218     for (size_t row = 0; row < header.height; row++) {
       
   219         // read row data, non-interlaced
       
   220         png_read_row(png, cache->mmap + row * header.row_bytes, NULL);
       
   221     }
       
   222 
       
   223     // done!
       
   224     return 0;
       
   225 }
       
   226 
       
   227 void pt_cache_destroy (struct pt_cache *cache)
       
   228 {
       
   229     free(cache->path);
       
   230 
       
   231     pt_cache_abort(cache);
       
   232 
       
   233     free(cache);
       
   234 }