Page 1 of 1

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

Posted: Thu Feb 25, 2010 11:40 am
by Paranoid
Originally posted in the 1.24.x forum but probably better suited here.

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 as I'd be unable to test it on the box running zm)