00001 #ifndef Impala_Core_VideoJob_Reporter_h
00002 #define Impala_Core_VideoJob_Reporter_h
00003
00004 #include "Basis/ILog.h"
00005 #include "Job/State.h"
00006 #include "Util/IOBufferFile.h"
00007 #include "Core/VideoJob/Data.h"
00008
00009 #include "Core/Array/Arrays.h"
00010 #include "Core/Array/Array2dTem.h"
00011 #include "Core/Array/Pattern/PtrFunc.h"
00012 #include "Core/Array/WritePng.h"
00013 #include "Core/VideoSet/VideoSet.h"
00014
00015 namespace Impala
00016 {
00017 namespace Core
00018 {
00019 namespace VideoJob
00020 {
00021
00022
00023
00024
00025
00026
00027 class Reporter
00028 {
00029 typedef Job::State::StateType JobStateType;
00030
00031 typedef Data::VideoMeta VideoMeta;
00032 typedef Data::VideoJob VideoJob;
00033
00034 typedef Core::Array::Array2dVec3UInt8 Array2dVec3UInt8;
00035 typedef Core::Array::Element::Vec3Int32 Vec3Int32;
00036
00037 public:
00038
00039 Reporter(const Data& data, CmdOptions& options) : mData(data), mStatusImage(0)
00040 {
00041 int nImageWidth = options.GetInt("imageWidth", 320);
00042 if (nImageWidth<320) nImageWidth = 320;
00043
00044
00045
00046 mStatusImageColWidth = 1 + Max<int>(2, nImageWidth / mData.VideoSetSize());
00047
00048 mStatusImageWidth = 1 + mStatusImageColWidth * mData.VideoSetSize();
00049 mStatusImageRowHeight = 1 + 12;
00050 mStatusImageHeight = 1 + mStatusImageRowHeight *
00051 mData.mProcessDef->StepCount();
00052
00053 SetupImage();
00054 }
00055
00056 ~Reporter()
00057 {
00058 delete mStatusImage;
00059 }
00060
00061 void
00062 WriteVideoSet(Core::VideoSet::VideoSet* videoSet) const
00063 {
00064 std::ofstream output("videoset.xml");
00065 if (!output.is_open())
00066 {
00067 ILOG_ERROR("Unable to write video file report");
00068 return;
00069 }
00070
00071 output << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl;
00072 output << "<?xml-stylesheet type=\"text/xsl\" href=\"videojobmanager.xslt\"?>" << std::endl;
00073 output << "<videoset>" << std::endl;
00074 int setSize = videoSet->NrFiles();
00075 for (int v = 0; v < setSize; v++)
00076 {
00077 String videoSpec = StringReplaceAll(videoSet->GetAsPath(v), "&",
00078 "&", false);
00079 output << " <video id=\"" << v << "\" text=\"" << videoSpec
00080 << "\" />" << std::endl;
00081 }
00082 output << "</videoset>" << std::endl;
00083 output.close();
00084 }
00085
00086 void
00087 WriteProcessDefinition() const
00088 {
00089 std::ofstream output("procdef.xml");
00090 if (!output.is_open())
00091 {
00092 ILOG_ERROR("Unable to write process definition report");
00093 return;
00094 }
00095
00096 output << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl;
00097 output << "<?xml-stylesheet type=\"text/xsl\" href=\"videojobmanager.xslt\"?>" << std::endl;
00098 output << "<procdef>" << std::endl;
00099 for (int s = 0; s < mData.mProcessDef->StepCount(); s++)
00100 output << " <step id=\"" << s << "\" text=\""
00101 << mData.mProcessDef->GetStep(s) << "\" />" << std::endl;
00102 output << "</procdef>" << std::endl;
00103 output.close();
00104 }
00105
00106 void
00107 WriteReportStatus() const
00108 {
00109
00110
00111 static const Vec3Int32 colorStateExcluded(128, 128, 128);
00112 static const Vec3Int32 colorStateInitial(190, 190, 190);
00113 static const Vec3Int32 colorStateScheduled(128, 128, 0);
00114 static const Vec3Int32 colorStateRunning(255, 255, 0);
00115 static const Vec3Int32 colorStateCompleted(0, 255, 0);
00116 static const Vec3Int32 colorStateFailed(255, 0, 0);
00117 static const Vec3Int32 colorStateUnknown(0, 0, 255);
00118
00119 const Vec3Int32* color = 0;
00120
00121 for (int stepID = 0; stepID < mData.mProcessDef->StepCount(); stepID++)
00122 {
00123 for (int vidID = 0; vidID < mData.VideoSetSize(); vidID++)
00124 {
00125
00126 if (mData.WasInitiallyMaskedOut(vidID))
00127 {
00128 color = &colorStateExcluded;
00129 }
00130 else
00131 {
00132 const VideoMeta& video = mData.mVideos.find(vidID)->second;
00133 if (stepID >= video.jobs.size())
00134 {
00135 if (video.discarded)
00136 color = &colorStateExcluded;
00137 else
00138 color = &colorStateInitial;
00139 }
00140 else
00141 {
00142 VideoJob* const job = video.jobs[stepID];
00143 switch (job->state)
00144 {
00145 case Job::State::CREATED:
00146 case Job::State::SUBMITTED:
00147 case Job::State::SCHEDULED:
00148 case Job::State::RESCHEDULED:
00149 color = &colorStateScheduled;
00150 break;
00151 case Job::State::RUNNING:
00152 color = &colorStateRunning;
00153 break;
00154 case Job::State::TERMINATED_NRM:
00155 if (job->exitCode != 0)
00156 color = &colorStateFailed;
00157 else
00158 color = &colorStateCompleted;
00159 break;
00160 case Job::State::TERMINATED_ABNRM:
00161 color = &colorStateFailed;
00162 break;
00163 default:
00164 ILOG_ERROR("Reporting unexpected job state: "
00165 << job->state);
00166 color = &colorStateUnknown;
00167 }
00168 }
00169 }
00170
00171
00172 int xOffset = vidID * mStatusImageColWidth + 1;
00173 int yOffset = stepID * mStatusImageRowHeight + 1;
00174 for (int x = 0; x < mStatusImageColWidth-1; x++)
00175 {
00176 int xAbs = xOffset + x;
00177 for (int y = 0; y < mStatusImageRowHeight-1; y++)
00178 {
00179 int yAbs = yOffset + y;
00180 Array::Pattern::PtrWrite(mStatusImage->CPB(xAbs, yAbs),
00181 *color);
00182 }
00183 }
00184 }
00185 }
00186
00187 CString imageFileName = "status.png";
00188 {
00189 Util::IOBufferFile buffer(imageFileName, false, false);
00190 Core::Array::WritePng(mStatusImage, &buffer);
00191 }
00192
00193
00194
00195
00196 std::ofstream output("vpdata.xml");
00197 if (!output.is_open())
00198 {
00199 ILOG_ERROR("unable to write report");
00200 return;
00201 }
00202
00203 output << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl;
00204 output << "<?xml-stylesheet type=\"text/xsl\" href=\"videojobmanager.xslt\"?>" << std::endl;
00205
00206 output << "<vpdata>" << std::endl << std::endl;
00207
00208 output << "<infos>" << std::endl;
00209 output << " <info label=\"video set file" << "\" text=\""
00210 << mData.mVideoSetName << "\"/>" << std::endl;
00211 output << " <info label=\"number of videos" << "\" text=\""
00212 << mData.mVideoSetSize << "\"/>" << std::endl;
00213 output << " <info label=\"process definition file" << "\" text=\""
00214 << mData.mProcessDefFile << "\"/>" << std::endl;
00215 output << " <info label=\"number of process steps" << "\" text=\""
00216 << mData.mProcessDef->StepCount() << "\"/>" << std::endl;
00217 output << " <info label=\"job server address" << "\" text=\""
00218 << mData.mServerName << ':' << mData.mPort << "\"/>" << std::endl;
00219
00220
00221 output << "</infos>" << std::endl << std::endl;
00222
00223 output << "<jobs>" << std::endl;
00224 for (int j = 0; j < mData.mAllJobs.size(); j++)
00225 {
00226 VideoJob* job = mData.mAllJobs[j];
00227 output << " <job id=\"" << job->id << "\" video=\""
00228 << job->videoNr << "\" step=\"" << job->stepNr
00229 << "\" state=\"" << job->state << "\" exit=\""
00230 << job->exitCode << "\"/>" << std::endl;
00231 }
00232 output << "</jobs>" << std::endl << std::endl;
00233
00234 output << "</vpdata>" << std::endl;
00235
00236 output.close();
00237 }
00238
00239 private:
00240
00241 void SetupImage()
00242 {
00243 static const Vec3Int32 colorBlack(0, 0, 0);
00244
00245 mStatusImage = Core::Array::ArrayCreate<Array2dVec3UInt8>
00246 (mStatusImageWidth, mStatusImageHeight, 0, 0);
00247
00248
00249 for (int x = 0; x <= mStatusImageWidth; x += mStatusImageColWidth)
00250 for (int y = 0; y < mStatusImageHeight; y++)
00251 Array::Pattern::PtrWrite(mStatusImage->CPB(x, y), colorBlack);
00252
00253
00254 for (int y = 0; y <= mStatusImageHeight; y += mStatusImageRowHeight)
00255 for (int x = 0; x < mStatusImageWidth; x++)
00256 Array::Pattern::PtrWrite(mStatusImage->CPB(x, y), colorBlack);
00257 }
00258
00259 ILOG_VAR_DECL;
00260
00261 const Data& mData;
00262
00263 int mStatusImageColWidth;
00264 int mStatusImageWidth;
00265 int mStatusImageRowHeight;
00266 int mStatusImageHeight;
00267
00268 Array2dVec3UInt8* mStatusImage;
00269
00270 };
00271
00272 ILOG_VAR_INIT(Reporter, Impala.Core.VideoJob);
00273
00274 }
00275 }
00276 }
00277
00278 #endif