]> git.sesse.net Git - vlc/blob - modules/media_library/media_pool.c
stream_filter/httplive.c: signal download thread on successfull index reload (live...
[vlc] / modules / media_library / media_pool.c
1 /*****************************************************************************
2  * media_pool.c : Media pool for watching system
3  *****************************************************************************
4  * Copyright (C) 2009-2010 the VideoLAN team and AUTHORS
5  * $Id$
6  *
7  * Authors: Srikanth Raju <srikiraju at gmail dot com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "sql_media_library.h"
25
26 #define mp_foreachlist( a, b ) for( ml_poolobject_t* b = a; b; b = b->p_next )
27
28 static inline int mediapool_hash( int media_id )
29 {
30     return media_id % ML_MEDIAPOOL_HASH_LENGTH;
31 }
32
33 /**
34  * @brief Get a media from the pool
35  * @param p_ml ML object
36  * @param media_id The media id of the object to get
37  * @return the found media or NULL if not found
38  */
39 ml_media_t* pool_GetMedia( media_library_t* p_ml, int media_id )
40 {
41     vlc_mutex_lock( &p_ml->p_sys->pool_mutex );
42     ml_media_t* p_media = NULL;
43     mp_foreachlist( p_ml->p_sys->p_mediapool[ mediapool_hash( media_id ) ], p_item )
44     {
45         if( p_item->p_media->i_id == media_id )
46         {
47             p_media = p_item->p_media;
48             break;
49         }
50     }
51     if( p_media )
52         ml_gc_incref( p_media );
53     vlc_mutex_unlock( &p_ml->p_sys->pool_mutex );
54     return p_media;
55 }
56
57 /**
58  * @brief Insert a media into the media pool
59  * @param p_ml ML object
60  * @param p_media Media object to insert
61  * @return VLC_SUCCESS or VLC_EGENERIC
62  */
63 int pool_InsertMedia( media_library_t* p_ml, ml_media_t* p_media, bool locked )
64 {
65     if( !locked )
66         ml_LockMedia( p_media );
67     assert( p_media );
68     assert( p_media->i_id > 0 );
69     vlc_spin_lock( &p_media->ml_gc_data.spin );
70     if( p_media->ml_gc_data.pool )
71     {
72         msg_Dbg( p_ml, "Already in pool! %s %d", p_media->psz_uri, p_media->i_id );
73         ml_UnlockMedia( p_media );
74         return VLC_EGENERIC;
75     }
76     p_media->ml_gc_data.pool = true;
77     vlc_spin_unlock( &p_media->ml_gc_data.spin );
78     int i_ret = VLC_SUCCESS;
79     vlc_mutex_lock( &p_ml->p_sys->pool_mutex );
80     mp_foreachlist( p_ml->p_sys->p_mediapool[ (mediapool_hash(p_media->i_id)) ], p_item )
81     {
82         if( p_media == p_item->p_media )
83         {
84             i_ret = VLC_EGENERIC;
85             break;
86         }
87         else if( p_media->i_id == p_item->p_media->i_id )
88         {
89             i_ret = VLC_EGENERIC;
90             msg_Warn( p_ml, "A media of the same id was found, but in different objects!" );
91             break;
92         }
93     }
94     if( i_ret == VLC_SUCCESS )
95     {
96         ml_poolobject_t* p_new = ( ml_poolobject_t * ) calloc( 1, sizeof( ml_poolobject_t* ) );
97         if( !p_new )
98             i_ret = VLC_EGENERIC;
99         else
100         {
101             ml_gc_incref( p_media );
102             p_new->p_media = p_media;
103             p_new->p_next = p_ml->p_sys->p_mediapool[ ( mediapool_hash( p_media->i_id ) ) ];
104             p_ml->p_sys->p_mediapool[ ( mediapool_hash( p_media->i_id ) ) ] = p_new;
105         }
106     }
107     vlc_mutex_unlock( &p_ml->p_sys->pool_mutex );
108     if( !locked )
109         ml_UnlockMedia( p_media );
110     return i_ret;
111 }
112
113 /**
114  * @brief Perform a single garbage collection scan on the media pool
115  * @param p_ml The ML object
116  * @note Scans all media and removes any medias not held by any other objects.
117  */
118 void pool_GC( media_library_t* p_ml )
119 {
120     vlc_mutex_lock( &p_ml->p_sys->pool_mutex );
121     ml_poolobject_t* p_prev = NULL;
122     ml_media_t* p_media = NULL;
123     for( int i_idx = 0; i_idx < ML_MEDIAPOOL_HASH_LENGTH; i_idx++ )
124     {
125         p_prev = NULL;
126         for( ml_poolobject_t* p_item = p_ml->p_sys->p_mediapool[ i_idx ];
127                 p_item != NULL; p_item = p_item->p_next )
128         {
129             p_media = p_item->p_media;
130             int refs;
131             vlc_spin_lock( &p_media->ml_gc_data.spin );
132             refs = p_media->ml_gc_data.refs;
133             vlc_spin_unlock( &p_media->ml_gc_data.spin );
134             if( refs == 1 )
135             {
136                 if( p_prev == NULL )
137                     p_ml->p_sys->p_mediapool[i_idx] = p_item->p_next;
138                 else
139                     p_prev->p_next = p_item->p_next;
140                 vlc_spin_lock( &p_media->ml_gc_data.spin );
141                 p_media->ml_gc_data.pool = false;
142                 vlc_spin_unlock( &p_media->ml_gc_data.spin );
143                 ml_gc_decref( p_item->p_media );//This should destroy the object
144                 free( p_item );
145             }
146             p_prev = p_item;
147         }
148     }
149     vlc_mutex_unlock( &p_ml->p_sys->pool_mutex );
150 }