/clients/cs/samples/YouTubeUploader/YouTubeUploader/insertandretry.cs
http://google-gdata.googlecode.com/ · C# · 246 lines · 187 code · 32 blank · 27 comment · 12 complexity · 4ef671ccbb0f623c768bd92f90d9dbeb MD5 · raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.IO;
- using System.Windows.Forms;
- using System.Diagnostics;
-
- using Google.GData.Client;
- using Google.GData.YouTube;
- using Google.GData.Tools;
- using Google.YouTube;
- using Google.GData.Extensions.MediaRss;
- using Google.GData.Client.ResumableUpload;
-
-
- /// this file contains the CSV related support code
- namespace YouTubeUploader {
- public partial class YouTubeUploader : Form {
- private ResumableUploader ru = null;
-
- /// <summary>
- /// userstate is the object that is passed to the async code to identify a particular upload
- /// this object remembers the http operation, the row in the spreadsheet, progress, etc.
- /// This object get's added to the the current queue, or the retryqueue
- /// </summary>
- internal class UserState {
- private DataGridViewRow row;
- private long currentPosition;
- private string httpVerb;
- private Uri resumeUri;
- private int retryCounter;
- private string errorText;
-
- internal UserState(DataGridViewRow r) {
- this.row = r;
- this.currentPosition = 0;
- this.retryCounter = 0;
- }
-
- internal DataGridViewRow Row {
- get {
- return this.row;
- }
- }
-
- internal long CurrentPosition {
- get {
- return this.currentPosition;
- }
- set {
- this.currentPosition = value;
- }
- }
-
- internal string Error {
- get {
- return this.errorText;
- }
- set {
- this.errorText = value;
- }
- }
-
- internal int RetryCounter {
- get {
- return this.retryCounter;
- }
- set {
- this.retryCounter = value;
- }
- }
-
- internal string HttpVerb {
- get {
- return this.httpVerb;
- }
- set {
- this.httpVerb = value;
- }
- }
-
- internal Uri ResumeUri {
- get {
- return this.resumeUri;
- }
- set {
- this.resumeUri = value;
- }
- }
- }
-
- // helper to create a ResumableUploader object and setup the event handlers
- private void EnsureRU() {
- this.ru = new ResumableUploader((int)this.ChunkSize.Value);
- this.ru.AsyncOperationCompleted += new AsyncOperationCompletedEventHandler(this.OnDone);
- this.ru.AsyncOperationProgress += new AsyncOperationProgressEventHandler(this.OnProgress);
- }
-
- // retry one row. The userstate was removed from the retry queue before that call
- private bool RetryRow(UserState us) {
- if (us != null) {
- Trace.Indent();
- Trace.TraceInformation("Retrying a row, current position is: " + us.CurrentPosition + "for uri: " + us.ResumeUri);
- Trace.Unindent();
- if (us.CurrentPosition > 0 && us.ResumeUri != null) {
- string contentType = MediaFileSource.GetContentTypeForFileName(us.Row.Cells[COLUMNINDEX_FILENAME].Value.ToString());
- MediaFileSource mfs = new MediaFileSource(us.Row.Cells[COLUMNINDEX_FILENAME].Value.ToString(), contentType);
-
- Stream s = mfs.GetDataStream();
- s.Seek(us.CurrentPosition, SeekOrigin.Begin);
-
- lock (this.flag) {
- this.queue.Add(us);
- }
- us.Row.Cells[COLUMNINDEX_STATUS].Value = "Retrying (" + us.RetryCounter + ") - Last error was: " + us.Error;
- ru.ResumeAsync(this.youTubeAuthenticator, us.ResumeUri, us.HttpVerb, s, contentType, us);
-
- return true;
- }
-
- // else treat this as a new one, a resume from null
- return InsertVideo(us.Row, us.RetryCounter + 1);
- }
- return false;
- }
-
- /// <summary>
- /// insert a new video.
- /// </summary>
- /// <param name="row"></param>
- /// <param name="retryCounter"></param>
- /// <returns></returns>
- private bool InsertVideo(DataGridViewRow row, int retryCounter) {
- Trace.TraceInformation("Entering InsertVideo: starting a new upload");
- Video v = new Video();
- v.Title = row.Cells[0].Value.ToString();
- v.Description = row.Cells[1].Value.ToString();
- v.Keywords = row.Cells[2].Value.ToString();
- v.Tags.Add(new MediaCategory(row.Cells[3].Value.ToString()));
- v.Private = row.Cells[4].Value.ToString().ToLower() == "true";
-
- string contentType = MediaFileSource.GetContentTypeForFileName(row.Cells[COLUMNINDEX_FILENAME].Value.ToString());
- v.MediaSource = new MediaFileSource(row.Cells[COLUMNINDEX_FILENAME].Value.ToString(), contentType);
-
- // add the upload uri to it
- AtomLink link = new AtomLink("http://uploads.gdata.youtube.com/resumable/feeds/api/users/" + this.youtubeAccount + "/uploads");
- link.Rel = ResumableUploader.CreateMediaRelation;
- v.YouTubeEntry.Links.Add(link);
-
- UserState u = new UserState(row);
- u.RetryCounter = retryCounter;
-
- lock (this.flag) {
- this.queue.Add(u);
- }
- ru.InsertAsync(this.youTubeAuthenticator, v.YouTubeEntry, u);
-
- row.Cells[COLUMNINDEX_STATUS].Value = "Queued up...";
- row.Cells[COLUMNINDEX_STATUS].Tag = u;
-
- return true;
- }
-
- // when an upload is completed successfully we parse the return stream
- // to setup the videoid.
- // also all retry counts will be reset to 0, as a successful upload incidates
- // a restored network condition (e.g.).
- private void ParseAndFinish(UserState u, Stream s) {
- YouTubeRequestSettings ys = new YouTubeRequestSettings(YouTubeUploader.ApplicationName,
- this.developerKey);
- YouTubeRequest ytr = new YouTubeRequest(ys);
- Video v = ytr.ParseVideo(s);
-
- Trace.TraceInformation("Upload successful");
- u.Row.Cells[COLUMNINDEX_STATUS].Value = "Upload successful";
- u.Row.Cells[COLUMNINDEX_STATUS].Tag = u;
- u.Row.Cells[COLUMNINDEX_VIDEOID].Value = v.VideoId;
- // we had one successful upload, reset the retry counts to 0
- lock (this.flag) {
- foreach (UserState us in retryQueue) {
- us.RetryCounter = 0;
- }
- }
- }
-
- private void RemoveFromProcessingQueue(UserState u) {
- lock (this.flag) {
- this.queue.Remove(u);
- }
- }
-
- private bool AddToRetryQueue(UserState u) {
- u.RetryCounter++;
- if (u.RetryCounter > (int)this.automaticRetries.Value) {
- u.Row.Cells[COLUMNINDEX_STATUS].Value = "Number of retries exceeded. Last error was: " + u.Error;
- return false;
- }
-
- lock (this.flag) {
- this.retryQueue.Add(u);
- }
- return true;
- }
-
- // moves an entry into the retry queue
- // and enables the retry timer
- private void TryARetry(UserState u) {
- if (AddToRetryQueue(u)) {
- this.RetryTimer.Enabled = true;
- }
- }
-
- // cancels all currently active threads and empties the queue
- private void CancelProcessingQueue() {
- // this will go over all rows and tries to upload them
- lock (this.flag) {
- this.RetryTimer.Enabled = false;
- foreach (UserState u in this.queue) {
- this.ru.CancelAsync(u);
- }
- this.queue = new List<UserState>();
- }
- }
-
- // walks over the retry queue and moves them into the processing queue
- // if the queue has free slots
- private void RetryRows() {
- if (this.retryQueue.Count > 0) {
- this.RetryTimer.Enabled = true;
- while (this.queue.Count < (int)this.MaxQueue.Value &&
- this.retryQueue.Count > 0) {
- lock (this.flag) {
- UserState u = this.retryQueue[0];
- this.retryQueue.Remove(u);
- RetryRow(u);
- }
- }
- } else {
- this.RetryTimer.Enabled = false;
- if (Finished())
- ToggleButtons(true);
- }
- }
- }
- }