Opened 12 years ago

Closed 12 years ago

#10151 closed Bug Report - General (fixed)

mythzoneminder and zoneminder > 1.23,x leads to broken paths

Reported by: dscoular@… Owned by: paulh
Priority: minor Milestone: 0.25
Component: Plugin - MythZoneminder Version: 0.24.1
Severity: medium Keywords:
Cc: Ticket locked: no

Description

Hi, I just recompiled zoneminder 1.24.4 via:

./configure --sysconfdir=/etc/zm --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-mysql=/usr  --with-webdir=/usr/share/zoneminder --with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin --with-webuser=www-data --with-webgroup=www-data --enable-crashtrace=no --enable-mmap=no
make;make install

In order to get shared memory back as recommended in the MythTV wiki for mythzoneminder.

However, the path to event images is now of the form:

/usr/share/zoneminder/events/1/11/11/05/.2860/001-capture.jpg

rather than the old 1.22.x path that mythzoneminder is looking for event images in:

/usr/share/zoneminder/events/1/2867/023-analyse.jpg

This means that all access to historical events is broken when using mythzoneminder and zoneminder > 1.23.x (I haven't test versions between 1.22.x and 1.24.4 but this is based on comments in the changelog). I think this is due to the zoneminder config variable now defaulting to ZM_USE_DEEP_STORAGE. However, even changing the default for this produces an event id prefixed by a "." and uses the word "capture" instead of "analysis" in the jpg filename.

mythzmserver uses the following logic (I think) to find event images:

    filepath = g_webPath + "/events/" + monitorID + "/" + eventID + "/";
    sprintf(str, m_eventFileFormat.c_str(), frameNo);
    filepath += str;

Whereas, the zoneminder code to build the path appears to be in http://svn.zoneminder.com/svn/zm/trunk/src/zm_event.cpp and uses the following logic:

    if ( config.use_deep_storage )
    {
        char *path_ptr = path;
        path_ptr += snprintf( path_ptr, sizeof(path), "%s/%d", config.dir_events, monitor->Id() );

        int dt_parts[6];
        dt_parts[0] = stime->tm_year-100;
        dt_parts[1] = stime->tm_mon+1;
        dt_parts[2] = stime->tm_mday;
        dt_parts[3] = stime->tm_hour;
        dt_parts[4] = stime->tm_min;
        dt_parts[5] = stime->tm_sec;

        char date_path[PATH_MAX] = "";
        char time_path[PATH_MAX] = "";
        char *time_path_ptr = time_path;
        for ( int i = 0; i < sizeof(dt_parts)/sizeof(*dt_parts); i++ )
        {
            path_ptr += snprintf( path_ptr, sizeof(path)-(path_ptr-path), "/%02d", dt_parts[i] );

            struct stat statbuf;
            errno = 0;
            stat( path, &statbuf );
            if ( errno == ENOENT || errno == ENOTDIR )
            {
                if ( mkdir( path, 0755 ) )
                {
                    Fatal( "Can't mkdir %s: %s", path, strerror(errno));
                }
            }
            if ( i == 2 )
                strncpy( date_path, path, sizeof(date_path) );
            else if ( i >= 3 )
                time_path_ptr += snprintf( time_path_ptr, sizeof(time_path)-(time_path_ptr-time_path), "%s%02d", i>3?"/":"", dt_parts[i] );
        }
        char id_file[PATH_MAX];
        // Create event id symlink
        snprintf( id_file, sizeof(id_file), "%s/.%d", date_path, id );
        if ( symlink( time_path, id_file ) < 0 )
            Fatal( "Can't symlink %s -> %s: %s", id_file, path, strerror(errno));
        // Create empty id tag file
        snprintf( id_file, sizeof(id_file), "%s/.%d", path, id );
        if ( FILE *id_fp = fopen( id_file, "w" ) )
            fclose( id_fp );
        else
            Fatal( "Can't fopen %s: %s", id_file, strerror(errno));
    }
    else
    {
        snprintf( path, sizeof(path), "%s/%d/%d", config.dir_events, monitor->Id(), id );
        
        struct stat statbuf;
        errno = 0;
        stat( path, &statbuf );
        if ( errno == ENOENT || errno == ENOTDIR )
        {
            if ( mkdir( path, 0755 ) )
            {
                Error( "Can't mkdir %s: %s", path, strerror(errno));
            }
        }
        char id_file[PATH_MAX];
        // Create empty id tag file
        snprintf( id_file, sizeof(id_file), "%s/.%d", path, id );
        if ( FILE *id_fp = fopen( id_file, "w" ) )
            fclose( id_fp );
        else
            Fatal( "Can't fopen %s: %s", id_file, strerror(errno));
    }
    last_db_frame = 0;
}

I suspect that mythzoneminder must adopt a similar logic if it is to be compatible with mythzoneminder >= 1.23.x.

As always, I could be wrong and perhaps there is a simple config change I'm overlooking. Any help much appreciated.

Cheers,

Doug

"The big print giveth and the small print taketh away"

Change History (2)

comment:1 Changed 12 years ago by Raymond Wagner

Priority: majorminor
Severity: highmedium
Status: newassigned

Resetting priority/severity to defaults.

comment:2 Changed 12 years ago by Github

Milestone: unknown0.25
Resolution: fixed
Status: assignedclosed

MythZoneMinder?: Add support for the deep filesystem hierarchy for events.

ZoneMinder? can use 2 different filesystem layouts to store the event images. This adds support for the layout you get when you turn on USE_DEEP_STORAGE.

This also changes the date/times in the event and event player screens to use MythDateTimeToString?() for consistency with other screens.

NOTE: This bumps the mythzmserver protocol version so both the server and all clients need to be updated.

Fixes #10151.

Branch: master Changeset: 4a2420ed195015173978efde9f1babed45cdc263

Note: See TracTickets for help on using tickets.