[vlc-devel] [PATCH] SQLite module
Srikanth Raju
srikiraju at gmail.com
Wed Nov 11 19:46:46 CET 2009
Hi,
2009/11/11 Rémi Denis-Courmont <remi at remlab.net>
> +if test "${SYS}" != "darwin"; then
> + PKG_ENABLE_MODULES_VLC([SQLITE], [], [sqlite3], [sqlite3], [auto])
> +else
> + AC_ARG_ENABLE(sqlite,
> + [ --enable-sqlite SQLite (default disabled)])
>
> AC_ARG_ENABLE is not supposed to be in a conditional.
>
> + if test "${enable_sqlite}" = "yes"
>
> This check is wrong. It will fail with --enable-sqlite=foobar.
>
> How do I fix this? This structure is used infinite other times.
> + then
> + AC_ARG_WITH(sqlite,
> + [ --with-sqlite=PATH sqlite path linking])
>
> Do we really need this? Also, same error as AC_ARG_ENABLE.
>
Yes, because Darwin doesn't have the latest sqlite.
And with this patch, we once again need sqlite_next_stmt(), as we're using
prepared statements
>
> +struct sql_sys_t
> +{
> + sqlite3 *db; /**< Database connection. */
> + vlc_mutex_t lock; /**< SQLite mutex. Threads are evil here. */
> + vlc_mutex_t trans_lock; /**< Mutex for running transactions */
> +};
>
> Why do you need two locks?
>
> One for transactions and one for threadsafe-ness.
Some sqlite builds can be non threadsafe. Better to be safe.
trans_lock ensures that no two threads can be running a transaction at one
time. Again, same issue as above.
+struct sql_stmt_t
> +{
> + sqlite3_stmt* p_sqlitestmt;
> +};
>
> Using the SQLite pointer directly would be simpler.
>
Maybe. But sql_stmt_t is used in vlc_sql.h. It wouldn't go well with other
sql modules
>
> + /* Initialize sys_t */
> + p_sql->p_sys = calloc( 1, sizeof( *p_sql->p_sys ) );
> + if( !p_sql->p_sys )
> + return VLC_ENOMEM;
> +
> + vlc_mutex_init( &p_sql->p_sys->lock );
> + vlc_mutex_init( &p_sql->p_sys->trans_lock );
> +
> + /* Open Database */
> + if( OpenDatabase( p_sql ) == VLC_SUCCESS )
> + msg_Dbg( p_sql, "sqlite module loaded" );
> + else
> + return VLC_EGENERIC;
>
> The error path is leaking.
>
Yes. Fixed.
>
> +static int OpenDatabase( sql_t *p_sql )
> +{
> + vlc_mutex_lock( &p_sql->p_sys->lock );
>
> Why do you need the mutex here?
Not required. Removed.
>
> + assert( !p_sql->p_sys->db );
>
> For a pedant, this is wrong since you are zeroing bits instead of
> NULLifying
> the pointer.
>
Hmm, although I don't understand how this matters, it still is the same...
changed it to p_sql->p_sys->db == NULL anyway
>
> +static int CloseDatabase( sql_t *p_sql )
> +{
> + vlc_mutex_lock( &p_sql->p_sys->lock );
>
> Why do you need the mutex here?
>
> Removed.
> + assert( p_sql->p_sys->db );
> +
> + /* Close database */
> + int i_ret = sqlite3_close( p_sql->p_sys->db );
> + p_sql->p_sys->db = NULL;
>
> What's the point? You're about to free p_sys anyway.
>
> + vlc_mutex_unlock( &p_sql->p_sys->lock );
> + return ( i_ret == SQLITE_OK ) ? VLC_SUCCESS : VLC_EGENERIC;
>
> The API does not allow failing to close the database...
>
Hmm, yes.
Fixed it.
>
> +static int Query( sql_t * p_sql,
> + const char * query,
> + char *** result,
> + int * nrow,
> + int * ncol )
> +{
> + vlc_mutex_lock( &p_sql->p_sys->lock );
> +
> + assert( p_sql->p_sys->db );
> +
> +#ifndef NDEBUG
> + msg_Dbg( p_sql, "Query: %s", query );
> +#endif
> + sqlite3_get_table( p_sql->p_sys->db, query, result, nrow, ncol, NULL
> );
> + if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
> + {
> + msg_Warn( p_sql, "sqlite3 error: %d: %s",
> + sqlite3_errcode( p_sql->p_sys->db ),
> + sqlite3_errmsg( p_sql->p_sys->db ) );
> + vlc_mutex_unlock( &p_sql->p_sys->lock );
> + return VLC_EGENERIC;
> + }
> +
> + vlc_mutex_unlock( &p_sql->p_sys->lock );
> + return VLC_SUCCESS;
> +}
>
> You could really factor vlc_mutex_unlock() while adding a return value
> variable here and in latter functions.
>
Yes.
>
> +static int GetTables( sql_t * p_sql,
> + char *** result )
> +{
> + int nrow, i_num = false;
>
> Assigning false to an integer is legal but weird.
>
> Yup. Fixed.
> +static char* VMSprintf( const char* psz_fmt, va_list args )
> +{
> + char *psz = sqlite3_vmprintf( psz_fmt, args );
> + char *ret = strdup( psz );
> + sqlite3_free( psz );
> + return ret;
> +}
>
> Do we really need this double copy/allocation?
>
Yes. psz is allocated with sqlite3_malloc. Some "fastmem" builds can use
different allocation strategies, hence we cannot rely on free() to free psz.
Hence the copy.
>
> +static int CommitTransaction( sql_t* p_sql )
> +{
> + assert( p_sql->p_sys->db );
> +
> + vlc_mutex_lock( &p_sql->p_sys->lock );
> +
> + /** This turns the auto commit on. */
> + sqlite3_exec( p_sql->p_sys->db, "COMMIT;", NULL, NULL, NULL );
> +#ifndef NDEBUG
> + msg_Dbg( p_sql, "Transaction Query: COMMIT;" );
> +#endif
> + if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
> + {
> + msg_Warn( p_sql, "sqlite3 error: %d: %s",
> + sqlite3_errcode( p_sql->p_sys->db ),
> + sqlite3_errmsg( p_sql->p_sys->db ) );
> + vlc_mutex_unlock( &p_sql->p_sys->lock );
>
> How does the caller recover from this? Is the transaction lock not stalled?
>
The transaction lock(I assume you mean trans_lock) is not locked on failure
The caller needs to call this function again. COMMITs may fail when there
are pending writes.
+static int RollbackTransaction( sql_t* p_sql )
> +{
> + assert( p_sql->p_sys->db );
> +
> + vlc_mutex_lock( &p_sql->p_sys->lock );
> +
> + sqlite3_exec( p_sql->p_sys->db, "ROLLBACK;", NULL, NULL, NULL );
> +#ifndef NDEBUG
> + msg_Dbg( p_sql, "Transaction Query: ROLLBACK;" );
> +#endif
> + if( sqlite3_errcode( p_sql->p_sys->db ) != SQLITE_OK )
> + {
> + msg_Warn( p_sql, "sqlite3 error: %d: %s",
> + sqlite3_errcode( p_sql->p_sys->db ),
> + sqlite3_errmsg( p_sql->p_sys->db ) );
> + vlc_mutex_unlock( &p_sql->p_sys->lock );
>
> Same stalling problem.
>
> IMHO, RollbackTransaction should return void, because it does not make much
> sense to fail here.
>
I agree that it should return void. However, the people who made sqlite
decided that a ROLLBACK can fail if there are pending reads/writes.
>
> +static sql_stmt_t* PrepareStatement( sql_t* p_sql, const char* psz_fmt,
> int
> i_length )
> +{
> + assert( p_sql->p_sys->db );
> + vlc_mutex_lock( &p_sql->p_sys->lock );
> + sql_stmt_t* p_stmt;
> + p_stmt = calloc( 1, sizeof( *p_stmt ) );
> + if( p_stmt == NULL )
> + {
> + vlc_mutex_unlock( &p_sql->p_sys->lock );
> + return NULL;
> + }
>
> Why do you need the lock to allocate memory?
>
> Fixed.
> --
> Rémi Denis-Courmont
> http://www.remlab.net/
>
--
Regards,
Srikanth Raju
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20091112/2bc468a5/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Sqlite-Module.patch
Type: application/octet-stream
Size: 26077 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20091112/2bc468a5/attachment.obj>
More information about the vlc-devel
mailing list