Merge branch 'storageareas' into zma_to_thread

pull/3122/head
Isaac Connor 2018-05-10 17:51:38 -04:00
commit c3053a2f8a
15 changed files with 467 additions and 149 deletions

View File

@ -439,7 +439,8 @@ sub start {
sigprocmask(SIG_BLOCK, $blockset, $sigset) or Fatal("Can't block SIGCHLD: $!");
Debug("forking");
if ( my $cpid = fork() ) {
#logReinit();
# This logReinit is required. Not sure why.
logReinit();
$process->{pid} = $cpid;
$process->{started} = time();
@ -503,6 +504,10 @@ sub start {
sub send_stop {
my ( $final, $process ) = @_;
my $sigset = POSIX::SigSet->new;
my $blockset = POSIX::SigSet->new(SIGCHLD);
sigprocmask(SIG_BLOCK, $blockset, $sigset) or die "dying at block...\n";
my $command = $process->{command};
if ( $process->{pending} ) {
@ -511,12 +516,19 @@ sub send_stop {
.strftime('%y/%m/%d %H:%M:%S', localtime())
."\n"
);
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
return();
}
my $pid = $process->{pid};
if ( !$pid ) {
dPrint(ZoneMinder::Logger::ERROR, "No process with command of '$command' is running\n");
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
return();
}
if ( !$pid_hash{$pid} ) {
dPrint(ZoneMinder::Logger::ERROR, "No process with command of '$command' pid $pid is running\n");
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
return();
}
@ -525,11 +537,12 @@ sub send_stop {
."\n"
);
$process->{keepalive} = !$final;
$process->{term_sent_at} = time;
$process->{term_sent_at} = time if ! $process->{term_sent_at};
$process->{pending} = 0;
$terminating_processes{$command} = $process;
kill('TERM', $pid);
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
return $pid;
} # end sub send_stop
@ -540,6 +553,16 @@ sub check_for_processes_to_kill {
sigprocmask(SIG_BLOCK, $blockset, $sigset) or die "dying at block...\n";
foreach my $command ( keys %terminating_processes ) {
my $process = $cmd_hash{$command};
if ( ! $process ) {
Debug("No process found for $command");
delete $terminating_processes{$command};
next;
}
if ( ! $$process{pid} ) {
Warning("Have no pid for $command.");
delete $terminating_processes{$command};
next;
}
my $now = time;
Debug("Have process $command at pid $$process{pid} $now - $$process{term_sent_at} = " . ( $now - $$process{term_sent_at} ));
if ( $$process{term_sent_at} and ( $now - $$process{term_sent_at} > KILL_DELAY ) ) {
@ -685,7 +708,7 @@ sub reaper {
} # end while waitpid
$SIG{CHLD} = \&reaper;
$! = $saved_status;
Debug("Leaving reaper");
Debug("Leaving reaper");
}
sub restartPending {
@ -697,7 +720,7 @@ sub restartPending {
start($process->{daemon}, @{$process->{args}});
}
}
dPrint(ZoneMinder::Logger::INFO, "done restartPending");
Debug("done restartPending");
}
sub shutdownAll {
@ -706,29 +729,17 @@ sub shutdownAll {
next if ! $pid_hash{$pid};
send_stop(1, $pid_hash{$pid});
}
my $count = KILL_DELAY;
while ( (keys %terminating_processes) and $count) {
while ( keys %terminating_processes ) {
check_for_processes_to_kill();
if ( %terminating_processes ) {
Debug("Still " . %terminating_processes . ' to die. count is: ' . $count . ' sleeping');
Debug("Still " . %terminating_processes . ' to die. sleeping');
sleep(1);
$count --;
}
}
foreach my $command ( keys %terminating_processes ) {
my $process = $cmd_hash{$command};
dPrint(ZoneMinder::Logger::WARNING, "'$$process{command}' has not stopped at "
.strftime('%y/%m/%d %H:%M:%S', localtime())
.' after ' . KILL_DELAY . ' seconds.'
." Sending KILL to pid $$process{pid}\n"
);
kill('KILL', $$process{pid});
dPrint(ZoneMinder::Logger::INFO, "Server shutdown at "
.strftime('%y/%m/%d %H:%M:%S', localtime())
."\n"
);
}
dPrint(ZoneMinder::Logger::INFO, 'Server shutdown at '
.strftime('%y/%m/%d %H:%M:%S', localtime())
."\n"
);
unlink(main::SOCK_FILE) or Error("Unable to unlink " . main::SOCK_FILE .". Error message was: $!") if ( -e main::SOCK_FILE );
unlink(ZM_PID) or Error("Unable to unlink " . ZM_PID .". Error message was: $!") if ( -e ZM_PID );
close(CLIENT);

View File

@ -1,53 +1,70 @@
//
// ZoneMinder Camera Class Implementation, $Date$, $Revision$
// Copyright (C) 2001-2008 Philip Coombes
//
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
//
#include "zm.h"
#include "zm_camera.h"
Camera::Camera( unsigned int p_monitor_id, SourceType p_type, unsigned int p_width, unsigned int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
monitor_id( p_monitor_id ),
type( p_type ),
width( p_width),
height( p_height ),
colours( p_colours ),
subpixelorder( p_subpixelorder ),
brightness( p_brightness ),
hue( p_hue ),
colour( p_colour ),
contrast( p_contrast ),
capture( p_capture ),
record_audio( p_record_audio ),
<<<<<<< HEAD
Camera::Camera(
unsigned int p_monitor_id,
SourceType p_type,
unsigned int p_width,
unsigned int p_height,
int p_colours,
int p_subpixelorder,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio
) :
monitor_id(p_monitor_id),
type(p_type),
width(p_width),
height(p_height),
colours(p_colours),
subpixelorder(p_subpixelorder),
brightness(p_brightness),
hue(p_hue),
colour(p_colour),
contrast(p_contrast),
capture(p_capture),
record_audio(p_record_audio),
mVideoStreamId(-1),
mAudioStreamId(-1),
mVideoCodecContext(NULL),
mAudioCodecContext(NULL),
video_stream(NULL)
video_stream(NULL),
record_audio(p_record_audio),
bytes(0)
{
pixels = width * height;
imagesize = pixels * colours;
Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",monitor_id,width,height,colours,subpixelorder,capture);
Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",
monitor_id,width,height,colours,subpixelorder,capture);
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 64) != 0) {
if ( (colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 64) != 0 ) {
Fatal("Image size is not multiples of 64");
} else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 64) != 0 || (imagesize % 12) != 0)) {
} else if ( colours == ZM_COLOUR_RGB24 && ((imagesize % 64) != 0 || (imagesize % 12) != 0) ) {
Fatal("Image size is not multiples of 12 and 64");
}
monitor = NULL;
@ -57,14 +74,12 @@ Camera::~Camera() {
}
Monitor *Camera::getMonitor() {
if ( ! monitor ) {
Warning("Loading monitor");
monitor = Monitor::Load( monitor_id, false, Monitor::QUERY );
}
if ( ! monitor )
monitor = Monitor::Load(monitor_id, false, Monitor::QUERY);
return monitor;
}
}
void Camera::setMonitor( Monitor *p_monitor ) {
void Camera::setMonitor(Monitor *p_monitor) {
monitor = p_monitor;
monitor_id = monitor->Id();
}

View File

@ -214,11 +214,13 @@ int FfmpegCamera::OpenFfmpeg() {
Debug(1, "Calling avformat_open_input for %s", mPath.c_str());
//mFormatContext = avformat_alloc_context( );
mFormatContext = avformat_alloc_context( );
// Speed up find_stream_info
//FIXME can speed up initial analysis but need sensible parameters...
//mFormatContext->probesize = 32;
//mFormatContext->max_analyze_duration = 32;
mFormatContext->interrupt_callback.callback = FfmpegInterruptCallback;
mFormatContext->interrupt_callback.opaque = this;
if ( avformat_open_input(&mFormatContext, mPath.c_str(), NULL, &opts) != 0 )
#endif
@ -480,4 +482,10 @@ int FfmpegCamera::Close() {
return 0;
} // end FfmpegCamera::Close
int FfmpegCamera::FfmpegInterruptCallback(void *ctx) {
//FfmpegCamera* camera = reinterpret_cast<FfmpegCamera*>(ctx);
return zm_terminate;
}
#endif // HAVE_LIBAVFORMAT

View File

@ -94,6 +94,8 @@ class FfmpegCamera : public Camera {
const std::string &Options() const { return( mOptions ); }
const std::string &Method() const { return( mMethod ); }
static int FfmpegInterruptCallback(void*ctx);
int PrimeCapture();
int PreCapture();
int Capture(ZMPacket &p);
@ -111,5 +113,4 @@ class FfmpegCamera : public Camera {
AVCodecContext *get_VideoCodecContext() { return mVideoCodecContext; };
AVCodecContext *get_AudioCodecContext() { return mAudioCodecContext; };
};
#endif // ZM_FFMPEG_CAMERA_H

View File

@ -18,6 +18,7 @@
*/
#include "zm.h"
#include "zm_signal.h"
#include "zm_libvlc_camera.h"
#if HAVE_LIBVLC
@ -39,7 +40,7 @@ void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) {
LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
bool newFrame = false;
for( uint32_t i = 0; i < data->bufferSize; i++ ) {
for( unsigned int i=0; i < data->bufferSize; i++ ) {
if ( data->buffer[i] != data->prevBuffer[i] ) {
newFrame = true;
break;
@ -56,11 +57,38 @@ void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) {
}
}
LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ) :
Camera( p_id, LIBVLC_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture, p_record_audio ),
mPath( p_path ),
mMethod( p_method ),
mOptions( p_options )
LibvlcCamera::LibvlcCamera(
int p_id,
const std::string &p_path,
const std::string &p_method,
const std::string &p_options,
int p_width,
int p_height,
int p_colours,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio
) :
Camera(
p_id,
LIBVLC_SRC,
p_width,
p_height,
p_colours,
ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours),
p_brightness,
p_contrast,
p_hue,
p_colour,
p_capture,
p_record_audio
),
mPath(p_path),
mMethod(p_method),
mOptions(p_options)
{
mLibvlcInstance = NULL;
mLibvlcMedia = NULL;
@ -70,15 +98,15 @@ LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::stri
mOptArgV = NULL;
/* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */
if(colours == ZM_COLOUR_RGB32) {
if ( colours == ZM_COLOUR_RGB32 ) {
subpixelorder = ZM_SUBPIX_ORDER_BGRA;
mTargetChroma = "RV32";
mBpp = 4;
} else if(colours == ZM_COLOUR_RGB24) {
} else if ( colours == ZM_COLOUR_RGB24 ) {
subpixelorder = ZM_SUBPIX_ORDER_BGR;
mTargetChroma = "RV24";
mBpp = 3;
} else if(colours == ZM_COLOUR_GRAY8) {
} else if ( colours == ZM_COLOUR_GRAY8 ) {
subpixelorder = ZM_SUBPIX_ORDER_NONE;
mTargetChroma = "GREY";
mBpp = 1;
@ -118,11 +146,13 @@ void LibvlcCamera::Initialise() {
void LibvlcCamera::Terminate() {
libvlc_media_player_stop(mLibvlcMediaPlayer);
if(mLibvlcData.buffer != NULL) {
if ( mLibvlcData.buffer ) {
zm_freealigned(mLibvlcData.buffer);
mLibvlcData.buffer = NULL;
}
if(mLibvlcData.prevBuffer != NULL) {
if ( mLibvlcData.prevBuffer ) {
zm_freealigned(mLibvlcData.prevBuffer);
mLibvlcData.prevBuffer = NULL;
}
}
@ -139,6 +169,8 @@ int LibvlcCamera::PrimeCapture() {
else if ( Method() == "rtpRtspHttp" )
opVect.push_back("--rtsp-http");
opVect.push_back("--no-audio");
if ( opVect.size() > 0 ) {
mOptArgV = new char*[opVect.size()];
Debug(2, "Number of Options: %d",opVect.size());
@ -149,17 +181,23 @@ int LibvlcCamera::PrimeCapture() {
}
}
mLibvlcInstance = libvlc_new (opVect.size(), (const char* const*)mOptArgV);
if ( mLibvlcInstance == NULL )
Fatal("Unable to create libvlc instance due to: %s", libvlc_errmsg());
mLibvlcInstance = libvlc_new(opVect.size(), (const char* const*)mOptArgV);
if ( mLibvlcInstance == NULL ) {
Error("Unable to create libvlc instance due to: %s", libvlc_errmsg());
return -1;
}
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
if(mLibvlcMedia == NULL)
Fatal("Unable to open input %s due to: %s", mPath.c_str(), libvlc_errmsg());
if ( mLibvlcMedia == NULL ) {
Error("Unable to open input %s due to: %s", mPath.c_str(), libvlc_errmsg());
return -1;
}
mLibvlcMediaPlayer = libvlc_media_player_new_from_media(mLibvlcMedia);
if(mLibvlcMediaPlayer == NULL)
Fatal("Unable to create player for %s due to: %s", mPath.c_str(), libvlc_errmsg());
if ( mLibvlcMediaPlayer == NULL ) {
Error("Unable to create player for %s due to: %s", mPath.c_str(), libvlc_errmsg());
return -1;
}
libvlc_video_set_format(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp);
libvlc_video_set_callbacks(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData);
@ -177,13 +215,17 @@ int LibvlcCamera::PrimeCapture() {
}
int LibvlcCamera::PreCapture() {
return(0);
return 0;
}
// Should not return -1 as cancels capture. Always wait for image if available.
int LibvlcCamera::Capture( ZMPacket &zm_packet ) {
while(!mLibvlcData.newImage.getValueImmediate())
// newImage is a mutex/condition based flag to tell us when there is an image available
while( !mLibvlcData.newImage.getValueImmediate() ) {
if (zm_terminate)
return 0;
mLibvlcData.newImage.getUpdatedValue(1);
}
mLibvlcData.mutex.lock();
zm_packet.image->Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp);
@ -194,7 +236,7 @@ int LibvlcCamera::Capture( ZMPacket &zm_packet ) {
}
int LibvlcCamera::PostCapture() {
return(0);
return 0;
}
#endif // HAVE_LIBVLC

View File

@ -332,7 +332,7 @@ bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) {
fprintf(stdout, "Content-Length: %d\r\n", img_buffer_size);
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
if ( ! zm_terminate )
Error("Unable to send stream frame: %s", strerror(errno));
Warning("Unable to send stream frame: %s", strerror(errno));
return false;
}
fputs("\r\n\r\n", stdout);
@ -409,7 +409,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
if ( !zm_terminate ){
// If the pipe was closed, we will get signalled SIGPIPE to exit, which will set zm_terminate
Error("Unable to send stream frame: %s", strerror(errno));
Warning("Unable to send stream frame: %s", strerror(errno));
}
return false;
}

View File

@ -144,31 +144,29 @@ template <class T> const T ThreadData<T>::getValue() const {
mMutex.lock();
const T valueCopy = mValue;
mMutex.unlock();
return( valueCopy );
return valueCopy;
}
template <class T> T ThreadData<T>::setValue( const T value ) {
template <class T> T ThreadData<T>::setValue(const T value) {
mMutex.lock();
const T valueCopy = mValue = value;
mMutex.unlock();
return( valueCopy );
return valueCopy;
}
template <class T> const T ThreadData<T>::getUpdatedValue() const {
Debug( 8, "Waiting for value update, %p", this );
Debug(8, "Waiting for value update, %p", this);
mMutex.lock();
mChanged = false;
//do {
mCondition.wait();
//} while ( !mChanged );
mCondition.wait();
const T valueCopy = mValue;
mMutex.unlock();
Debug( 9, "Got value update, %p", this );
return( valueCopy );
Debug(9, "Got value update, %p", this);
return valueCopy;
}
template <class T> const T ThreadData<T>::getUpdatedValue( double secs ) const {
Debug( 8, "Waiting for value update, %.2f secs, %p", secs, this );
template <class T> const T ThreadData<T>::getUpdatedValue(double secs) const {
Debug(8, "Waiting for value update, %.2f secs, %p", secs, this);
mMutex.lock();
mChanged = false;
//do {
@ -176,41 +174,41 @@ template <class T> const T ThreadData<T>::getUpdatedValue( double secs ) const {
//} while ( !mChanged );
const T valueCopy = mValue;
mMutex.unlock();
Debug( 9, "Got value update, %p", this );
return( valueCopy );
Debug(9, "Got value update, %p", this );
return valueCopy;
}
template <class T> const T ThreadData<T>::getUpdatedValue( int secs ) const {
Debug( 8, "Waiting for value update, %d secs, %p", secs, this );
template <class T> const T ThreadData<T>::getUpdatedValue(int secs) const {
Debug(8, "Waiting for value update, %d secs, %p", secs, this);
mMutex.lock();
mChanged = false;
//do {
mCondition.wait( secs );
mCondition.wait(secs);
//} while ( !mChanged );
const T valueCopy = mValue;
mMutex.unlock();
Debug( 9, "Got value update, %p", this );
return( valueCopy );
Debug(9, "Got value update, %p", this);
return valueCopy;
}
template <class T> void ThreadData<T>::updateValueSignal( const T value ) {
Debug( 8, "Updating value with signal, %p", this );
template <class T> void ThreadData<T>::updateValueSignal(const T value) {
Debug(8, "Updating value with signal, %p", this);
mMutex.lock();
mValue = value;
mChanged = true;
mCondition.signal();
mMutex.unlock();
Debug( 9, "Updated value, %p", this );
Debug(9, "Updated value, %p", this);
}
template <class T> void ThreadData<T>::updateValueBroadcast( const T value ) {
Debug( 8, "Updating value with broadcast, %p", this );
Debug(8, "Updating value with broadcast, %p", this);
mMutex.lock();
mValue = value;
mChanged = true;
mCondition.broadcast();
mMutex.unlock();
Debug( 9, "Updated value, %p", this );
Debug(9, "Updated value, %p", this);
}
Thread::Thread() :

View File

@ -125,6 +125,9 @@ class EventsController extends AppController {
$event['Event']['Next'] = $event_neighbors['next']['Event']['Id'];
$event['Event']['Prev'] = $event_neighbors['prev']['Event']['Id'];
$event['Event']['fileExists'] = $this->Event->fileExists($event['Event']);
$event['Event']['fileSize'] = $this->Event->fileSize($event['Event']);
# Also get the previous and next events for the same monitor
$event_monitor_neighbors = $this->Event->find('neighbors', array(
'conditions'=>array('Event.MonitorId'=>$event['Event']['MonitorId'])

View File

@ -30,20 +30,37 @@ class HostController extends AppController {
));
}
function getAuthHash() {
if ( $zmOptAuth == '1' ) {
require_once '../../../includes/auth.php';
$this->set(array(
'auth_hash' => generateAuthHash(ZM_AUTH_HASH_IPS),
'_serialize' => array('auth_hash')
) );
} else {
$this->set(array(
'auth_hash' => '',
'_serialize' => array('auth_hash')
) );
function getCredentials() {
// ignore debug warnings from other functions
$this->view='Json';
$credentials = "";
$appendPassword = 0;
$this->loadModel('Config');
$isZmAuth = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH')))['Config']['Value'];
if ($isZmAuth) {
$zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value'];
if ($zmAuthRelay == 'hashed') {
$zmAuthHashIps= $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_IPS')))['Config']['Value'];
$credentials = 'auth='.generateAuthHash($zmAuthHashIps);
}
elseif ($zmAuthRelay == 'plain') {
// user will need to append the store password here
$credentials = "user=".$this->Session->read('user.Username')."&pass=";
$appendPassword = 1;
}
elseif ($zmAuthRelay == 'none') {
$credentials = "user=".$this->Session->read('user.Username');
}
}
}
$this->set(array(
'credentials'=> $credentials,
'append_password'=>$appendPassword,
'_serialize' => array('credentials', 'append_password')
) );
}
// If $mid is set, only return disk usage for that monitor
// Else, return an array of total disk usage, and per-monitor

View File

@ -44,7 +44,15 @@ class Event extends AppModel {
'conditions' => '',
'fields' => '',
'order' => ''
)
),
'Storage' => array(
'className' => 'Storage',
'joinTable' => 'Storage',
'foreignKey' => 'StorageId',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
/**
@ -92,4 +100,40 @@ class Event extends AppModel {
),
);
public function Relative_Path($event) {
$event_path = '';
if ( $event['Scheme'] == 'Deep' ) {
$event_path = $event['MonitorId'] .'/'.strftime('%y/%m/%d/%H/%M/%S', strtotime($event['StartTime']));
} else if ( $event['Scheme'] == 'Medium' ) {
$event_path = $event['MonitorId'] .'/'.strftime('%Y-%m-%d', strtotime($event['StartTime'])) . '/'.$event['Id'];
} else {
$event_path = $event['MonitorId'] .'/'.$event['Id'];
}
return $event_path;
} // end function Relative_Path()
public function fileExists($event) {
//$data = $this->findById($id);
//return $data['Event']['dataset_filename'];
$storage = $this->Storage->findById($event['StorageId']);
if ( $event['DefaultVideo'] ) {
if ( file_exists($storage['Storage']['Path'].'/'.$this->Relative_Path($event).'/'.$event['DefaultVideo']) ) {
return 1;
} else {
Logger::Debug("FIle does not exist at " . $storage['Storage']['Path'].'/'.$this->Relative_Path($event).'/'.$event['DefaultVideo'] );
}
} else {
Logger::Debug("No DefaultVideo in Event" . $this->Event);
return 0;
}
} // end function fileExists($event)
public function fileSize($event) {
$storage = $this->Storage->findById($event['StorageId']);
return filesize($storage['Storage']['Path'].'/'.$this->Relative_Path($event).'/'.$event['DefaultVideo']);
}
}

View File

@ -0,0 +1,69 @@
<?php
App::uses('AppModel', 'Model');
/**
* Storage Model
*
* @property Event $Event
* @property Zone $Zone
*/
class Storage extends AppModel {
/**
* Use table
*
* @var mixed False or table name
*/
public $useTable = 'Storage';
/**
* Primary key field
*
* @var string
*/
public $primaryKey = 'Id';
/**
* Display field
*
* @var string
*/
public $displayField = 'Name';
public $recursive = -1;
/**
* Validation rules
*
* @var array
*/
public $validate = array(
'Id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
/**
* hasMany associations
*
* @var array
*/
public $belongsTo = array(
'Server' => array(
'className' => 'Server',
'foreignKey' => 'ServerId',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
)
);
}

View File

@ -522,6 +522,94 @@ class Event {
return '<a href="?view=event&amp;eid='. $this->{'Id'}.'">'.$text.'</a>';
}
public function file_exists() {
if ( file_exists( $this->Path().'/'.$this->DefaultVideo() ) ) {
return true;
}
$Storage= $this->Storage();
$Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server();
if ( $Server->Id() != ZM_SERVER_ID ) {
$url = $Server->Url() . '/zm/api/events/'.$this->{'Id'}.'.json';
if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) {
$url .= '?auth='.generateAuthHash( ZM_AUTH_HASH_IPS );
} elseif ( ZM_AUTH_RELAY == 'plain' ) {
$url = '?user='.$_SESSION['username'];
$url = '?pass='.$_SESSION['password'];
} elseif ( ZM_AUTH_RELAY == 'none' ) {
$url = '?user='.$_SESSION['username'];
}
}
Logger::Debug("sending command to $url");
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'GET',
'content' => ''
)
);
$context = stream_context_create($options);
try {
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */
Error("Error restarting zmc using $url");
}
$event_data = json_decode($result,true);
Logger::Debug(print_r($event_data['event']['Event'],1));
return $event_data['event']['Event']['fileExists'];
} catch ( Exception $e ) {
Error("Except $e thrown trying to get event data");
}
} # end if not local
return false;
} # end public function file_exists()
public function file_size() {
if ( file_exists($this->Path().'/'.$this->DefaultVideo()) ) {
return filesize($this->Path().'/'.$this->DefaultVideo());
}
$Storage= $this->Storage();
$Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server();
if ( $Server->Id() != ZM_SERVER_ID ) {
$url = $Server->Url() . '/zm/api/events/'.$this->{'Id'}.'.json';
if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) {
$url .= '?auth='.generateAuthHash( ZM_AUTH_HASH_IPS );
} elseif ( ZM_AUTH_RELAY == 'plain' ) {
$url = '?user='.$_SESSION['username'];
$url = '?pass='.$_SESSION['password'];
} elseif ( ZM_AUTH_RELAY == 'none' ) {
$url = '?user='.$_SESSION['username'];
}
}
Logger::Debug("sending command to $url");
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'GET',
'content' => ''
)
);
$context = stream_context_create($options);
try {
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */
Error("Error restarting zmc using $url");
}
$event_data = json_decode($result,true);
Logger::Debug(print_r($event_data['event']['Event'],1));
return $event_data['event']['Event']['fileSize'];
} catch ( Exception $e ) {
Error("Except $e thrown trying to get event data");
}
} # end if not local
return 0;
} # end public function file_size()
} # end class
?>

View File

@ -182,6 +182,7 @@ if ( 0 ) {
}
return $this->{'DiskSpace'};
} // end function event_disk_space
public function Server() {
if ( ! array_key_exists('Server',$this) ) {
$this->{'Server'}= new Server( $this->{'ServerId'} );

View File

@ -195,16 +195,15 @@ $html .= htmlSelect( 'Status[]', $status_options,
$Monitor = new Monitor($monitors[$i]);
ini_set('track_errors', 'on');
$php_errormsg = '';
@preg_match($_SESSION['MonitorName'], '');
if ( !$php_errormsg ) {
# regexp is valid
if ( !preg_match($_SESSION['MonitorName'], $Monitor->Name()) ) {
continue;
}
} else {
if ( ! strstr($Monitor->Name(), $_SESSION['MonitorName']) ) {
continue;
}
$regexp = $_SESSION['MonitorName'];
@preg_match($regexp, '');
if ( $php_errormsg ) {
$regexp = '/'.preg_quote($regexp,'/').'/i';
}
if ( !preg_match($regexp, $Monitor->Name()) ) {
continue;
}
}
@ -212,16 +211,14 @@ $html .= htmlSelect( 'Status[]', $status_options,
$Monitor = new Monitor($monitors[$i]);
ini_set('track_errors', 'on');
$php_errormsg = '';
@preg_match($_SESSION['Source'], '');
if ( !$php_errormsg ) {
# regexp is valid
if ( !preg_match($_SESSION['Source'], $Monitor->Source()) ) {
continue;
}
} else {
if ( ! strstr($Monitor->Source(), $_SESSION['Source']) ) {
continue;
}
$regexp = $_SESSION['Source'];
@preg_match($regexp, '');
if ( $php_errormsg ) {
$regexp = '/'.preg_quote($regexp,'/').'/i';
}
if ( !preg_match($regexp, $Monitor->Source()) ) {
continue;
}
}

View File

@ -27,14 +27,15 @@ ob_end_clean();
noCacheHeaders();
xhtmlHeaders( __FILE__, translate('Console') );
if ( !isset($_REQUEST['minTime']) && !isset($_REQUEST['maxTime']) ) {
$time = time();
$maxTime = strftime('%FT%T',$time - 3600);
$minTime = strftime('%FT%T',$time - (2*3600) );
} else if ( isset($_REQUEST['minTime']) ) {
if ( isset($_REQUEST['minTime']) ) {
$minTime = validHtmlStr($_REQUEST['minTime']);
} else if ( isset($_REQUEST['maxTime']) ) {
} else {
$minTime = strftime('%FT%T',time() - (2*3600) );
}
if ( isset($_REQUEST['maxTime']) ) {
$maxTime = validHtmlStr($_REQUEST['maxTime']);
} else {
$maxTime = strftime('%FT%T',time() - 3600);
}
$filter = array(
@ -63,8 +64,6 @@ parseFilter($filter);
$filterQuery = $filter['query'];
Logger::Debug($filterQuery);
$eventsSql = 'SELECT *,
UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs,
UNIX_TIMESTAMP(EndTime) AS EndTimeSecs
@ -91,7 +90,7 @@ $EventsByMonitor = array();
while( $event = $result->fetch(PDO::FETCH_ASSOC) ) {
$Event = new Event($event);
if ( ! isset($EventsByMonitor[$event['MonitorId']]) )
$EventsByMonitor[$event['MonitorId']] = array( 'Events'=>array(), 'MinGap'=>0, 'MaxGap'=>0, 'FileMissing'=>0, 'ZeroSize'=>array() );
$EventsByMonitor[$event['MonitorId']] = array( 'Events'=>array(), 'MinGap'=>0, 'MaxGap'=>0, 'FileMissing'=>array(), 'ZeroSize'=>array() );
if ( count($EventsByMonitor[$event['MonitorId']]['Events']) ) {
$last_event = end($EventsByMonitor[$event['MonitorId']]['Events']);
@ -104,9 +103,9 @@ while( $event = $result->fetch(PDO::FETCH_ASSOC) ) {
$EventsByMonitor[$event['MonitorId']]['MaxGap'] = $gap;
} # end if has previous events
if ( ! file_exists( $Event->Path().'/'.$Event->DefaultVideo() ) ) {
$EventsByMonitor[$event['MonitorId']]['FileMissing'] += 1;
} else if ( ! filesize( $Event->Path().'/'.$Event->DefaultVideo() ) ) {
if ( ! $Event->file_exists() ) {
$EventsByMonitor[$event['MonitorId']]['FileMissing'][] = $Event;
} else if ( ! $Event->file_size() ) {
$EventsByMonitor[$event['MonitorId']]['ZeroSize'][] = $Event;
}
$EventsByMonitor[$event['MonitorId']]['Events'][] = $Event;
@ -169,12 +168,33 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
} else {
$MinGap = 0;
$MaxGap = 0;
$FileMissing = 0;
$ZeroSize = 0;
$FileMissing = array();
$ZeroSize = array();
$FirstEvent = 0;
$LastEvent = 0;
}
if ( count($FileMissing) ) {
$FileMissing_filter = array(
'Query' => array(
'terms' => array(
array('attr'=>'Id','op'=>'IN', 'val'=>implode(',',array_map(function($Event){return $Event->Id();},$FileMissing)))
)
)
);
parseFilter($FileMissing_filter);
}
if ( count($ZeroSize) ) {
$ZeroSize_filter = array(
'Query' => array(
'terms' => array(
array('attr'=>'Id','op'=>'IN', 'val'=>implode(',',array_map(function($Event){return $Event->Id();},$ZeroSize)))
)
)
);
}
?>
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>">
<td class="colId"><a href="<?php echo $montagereview_link ?>"><?php echo $monitor['Id'] ?></a></td>
@ -195,8 +215,12 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
<td class="colLastEvent"><?php echo $LastEvent ? $LastEvent->link_to($LastEvent->Id().' at ' . $LastEvent->StartTime()) : 'none'?></td>
<td class="colMinGap"><?php echo $MinGap ?></td>
<td class="colMaxGap"><?php echo $MaxGap ?></td>
<td class="colFileMissing<?php echo $FileMissing ? ' errorText' : ''?>"><?php echo $FileMissing ?></td>
<td class="colZeroSize<?php echo count($ZeroSize) ? ' errorText' : ''?>"><?php echo count($ZeroSize) ?></td>
<td class="colFileMissing<?php echo count($FileMissing) ? ' errorText' : ''?>">
<?php echo count($FileMissing) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW .'&amp;page=1'.$FileMissing_filter['query'].'">'.count($FileMissing).'</a>' : '0' ?>
</td>
<td class="colZeroSize<?php echo count($ZeroSize) ? ' errorText' : ''?>">
<?php echo count($ZeroSize) ? '<a href="?view='.ZM_WEB_EVENTS_VIEW .'&amp;page=1'.$ZeroSize_filter['query'].'">'.count($FileMissing).'</a>' : '0' ?>
</td>
</tr>
<?php
} # end for each monitor