public static void DirectWrite(FrameWithTicks frame, int streamID) { Index ind = new Index(); ind.start = 0; ind.end = frame.frame.Length - 1; ind.timestamp = frame.ticks; DBHelper.SaveBufferAndIndices(streamID, new Index[] { ind }, 1, (byte[])frame.frame); }
public static void DirectWrite(FrameWithTicks frame, int streamID) { Trace.WriteLine(String.Format("BufferRecorder::DirectWrite called with frame of size {0} bytes and steamID {1}.", frame.frame.Length, streamID)); Index ind = new Index(); ind.start = 0; ind.end = frame.frame.Length - 1; ind.timestamp = frame.ticks; DBHelper.SaveBufferAndIndices(streamID, new Index[] { ind }, 1, (byte[])frame.frame); }
/// <summary> /// Writes the buffer to SQL and empties it. /// </summary> private void WriteData() { lock (this) { // This and the lock are to circumvent a small multithreading dillema if (this.Available) { Trace.WriteLine(String.Format("BufferRecorder::WriteData called when Available at time {0}. Returning.", DateTime.Now.Ticks)); return; } // Going to try a spin-wait just to see if we can resolve this multithreading problem while (this.writing) { Thread.Sleep(10); } writing = true; bool overflowed; do { overflowed = false; try { // Don't try to write an empty buffer if (currentIndex > 0) { #if TIMING long startTimer = DateTime.Now.Ticks; #endif // TODO: Find out why this gets called twice on one data set OR find a workaround. Trace.WriteLine(String.Format("BufferRecorder::WriteData doing SBAI on buffer {0}, stream {1} at {2}", number, streamID, DateTime.Now.Ticks)); DBHelper.SaveBufferAndIndices( this.streamID, this.indices, this.currentIndex, buffer); #if TIMING long takenTime = DateTime.Now.Ticks - startTimer; Trace.WriteLine("TIMING: SBAI took: " + (takenTime / Constants.TicksPerMs) + " ms"); #endif } } catch (SqlException ex) { // Catch the overflow case, where we have more data than the 'int' type holds if (ex.Message.ToLower().IndexOf("overflow") >= 0) { overflowed = true; // by setting this, we directly try to write the data again this.Overflowed(this, EventArgs.Empty); } // Two exceptions are seen here: // Timeouts in SQL due to taking a *really* bad performance beating // OR Constraint violation in Frame table due to unusual multithreading problem not yet solved (mentioned above) // Dont do anything, b/c failed DB ops are already event-logged. Just move on & hope that the stream is playable. } catch (InvalidOperationException ex) { // In the worst of performance cases, we run out of pooled connections and get this exception eventLog.WriteEntry("Database operation failed. Exception: \n" + ex.ToString(), EventLogEntryType.Error, ArchiveServiceEventLog.ID.DBOpFailed); // Again, ignore & move on, dropping the frames. } } // In the specific case where we've overflowed, try again immediately (to hopefully preempt other buffers from going out-of-order) while (overflowed); writing = false; isAvailable = true; bufferIndex = 0; currentIndex = 0; Trace.WriteLine("BufferRecorder::WriteData completed."); } }