Page 1 of 1

BUG: zma exits with large values of Pre Event Image Count

Posted: Tue Feb 23, 2010 9:05 pm
by Paranoid
When "Pre Event Image Count" is greater than about 170 zma will exit abnormally.

I've tracked it down to Event::AddFrames zm_event.cpp

Code: Select all

void Event::AddFrames( int n_frames, Image **images, struct timeval **timestamps )
{
    static char sql[BUFSIZ];
    strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", BUFSIZ );
    for ( int i = 0; i < n_frames; i++ )
    {
        frames++;

        static char event_file[PATH_MAX];
        snprintf( event_file, sizeof(event_file), capture_file_format, path, frames );

        Debug( 1, "Writing pre-capture frame %d", frames );
        WriteFrameImage( images[i], *(timestamps[i]), event_file );

        struct DeltaTimeval delta_time;
        DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 );

        int sql_len = strlen(sql);
        snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
    }

    Debug( 1, "Adding %d frames to DB", n_frames );
    *(sql+strlen(sql)-2) = '\0';
    if ( mysql_query( &dbconn, sql ) )
    {
        Error( "Can't insert frames: %s", mysql_error( &dbconn ) );
        exit( mysql_errno( &dbconn ) );
    }
    last_db_frame = frames;
}

With large values of n_frames the sql buffer fills up (it doesn't overflow) and mysql_query ends up being called with a malformed sql statement. This results in an error and zma exits.

The solution may be to save the frames in smaller numbers. An example of how this could be done is shown below:

Code: Select all

void Event::AddFrames( int n_frames, Image **images, struct timeval **timestamps )
{
    static char sql[BUFSIZ];
    strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", BUFSIZ );
    for ( int i = 0; i < n_frames; i++ )
    {
        frames++;

        static char event_file[PATH_MAX];
        snprintf( event_file, sizeof(event_file), capture_file_format, path, frames );

        Debug( 1, "Writing pre-capture frame %d", frames );
        WriteFrameImage( images[i], *(timestamps[i]), event_file );

        struct DeltaTimeval delta_time;
        DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 );

        int sql_len = strlen(sql);
        snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
        if ( i && i % 100 == 0 )
        {
            Debug( 1, "Adding %d/%d frames to DB", i, n_frames );
            *(sql+strlen(sql)-2) = '\0';
            if ( mysql_query( &dbconn, sql ) )
            {
                Error( "Can't insert frames: %s", mysql_error( &dbconn ) );
                exit( mysql_errno( &dbconn ) );
            }
            strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", BUFSIZ );
        }
    }

    if( (n_frames - 1) % 100 )
    {
        Debug( 1, "Adding %d frames to DB", n_frames );
        *(sql+strlen(sql)-2) = '\0';
        if ( mysql_query( &dbconn, sql ) )
        {
            Error( "Can't insert frames: %s", mysql_error( &dbconn ) );
            exit( mysql_errno( &dbconn ) );
        }
    }
    last_db_frame = frames;
}
The above code is untested (I haven't even tried to compile it).