/// <summary> /// Returns the free busy times for the specified exchange users /// </summary> /// <param name="users">The user which free/busy blocks will be looked up for</param> /// <param name="window">The time period to look up FB info for</param> /// <returns></returns> public Dictionary <ExchangeUser, FreeBusy> LookupFreeBusyTimes( ExchangeUserDict users, DateTimeRange window) { /* Create an array of mailboxes to retrieve from exchange */ Dictionary <ExchangeUser, FreeBusy> result = new Dictionary <ExchangeUser, FreeBusy>(); try { using (BlockTimer bt = new BlockTimer("LookupFreeBusyTimes")) { /* Perform the retrieval of free busy times through WebDav */ result = webDavQuery.LoadFreeBusy(exchangeServerUrl, users, window); } } catch (Exception ex) { throw new GCalExchangeException( GCalExchangeErrorCode.ExchangeUnreachable, "Error occured while retrieving free busy ranges", ex); } return(result); }
/// <summary> /// Load a set of appointments from the server /// </summary> /// <param name="folderUrl">The mailbox URL</param> /// <param name="start">Start time of date range to fetch</param> /// <param name="end">End time of date range to fetch</param> /// <returns>A list of appointments from the mailbox</returns> public virtual List <Appointment> LoadAppointments( string folderUrl, DateTime start, DateTime end) { using (BlockTimer bt = new BlockTimer("LoadAppointments")) { string request = WebDavXmlResources.GetText( WebDavXmlResources.FindAppointments, folderUrl, DateUtil.FormatDateForDASL(start), DateUtil.FormatDateForDASL(end)); string response = IssueRequestAndFetchReponse(folderUrl, Method.SEARCH, request); XmlDocument responseXML = ParseExchangeXml(response); return(ParseAppointmentResultSetXml(responseXML)); } }
private EventFeed QueryGCal(FeedQuery query, string userName, DateTime modifiedSince) { if (log.IsInfoEnabled) { log.Info(String.Format("Querying GCal for User '{0}': {1}", userName, query.Uri)); } EventFeed feed = null; // Wait as necessary before making new request. connectionThrottler.WaitBeforeNewConnection(); try { using (BlockTimer bt = new BlockTimer("QueryGCal")) { feed = service.Query(query, modifiedSince) as EventFeed; } } catch (GDataNotModifiedException e) { // Content was not modified log.InfoFormat("NotModified: {0}", e.Message); } catch (Exception) { // Report a failure, regardless of the exception, as long as it is not GDataNotModifiedException. // This could be a bit overly aggressive, but it is hard to make bets // what exception was caught and rethrown in GData and what was let to fly. connectionThrottler.ReportFailure(); throw; } // Everything went well, report it. // Note this is valid even when we caught GDataNotModifiedException. connectionThrottler.ReportSuccess(); LogResponse(feed, userName); return(feed); }
/// <summary> /// Perform sync of users from Google Calendar to Exchnage until there are no more /// users to sync. This can be called from a worker thread. /// </summary> public void SyncUsers() { ExchangeUser user; int userCount = 0; string login = string.Empty; errorThreshold = ConfigCache.ServiceErrorCountThreshold; errorCount = 0; while (exchangeUsers.Count > 0) { lock ( lockObject ) { if (exchangeUsers.Count == 0) { break; } else { user = exchangeUsers[0]; exchangeUsers.RemoveAt(0); } } try { userCount++; login = user.Email.ToLower(); DateTime modifiedDate = modifiedDateUtil.GetModifiedDateForUser(login); DateTime currentDate = DateUtil.NowUtc; // Pick a window to synchronize for: // // [-N, +2N] days where N is settable in the config file // // Scanning back in time is necessary so that we pickup changes to meetings and events that were // made invisible. // // TODO: The window we're syncing for should also be used when we modify events in Exchange // so we only modify events in the window. DateTime start = currentDate.AddDays(-ConfigCache.GCalSyncWindow); DateTime end = currentDate.AddDays(2 * ConfigCache.GCalSyncWindow); DateTimeRange syncWindow = new DateTimeRange(start, end); log.InfoFormat("Processing user {0} for {1}", login, syncWindow); EventFeed feed = gcalGateway.QueryGCal( user.Email, GCalVisibility.Private, ConfigCache.FreeBusyDetailLevel, modifiedDate, syncWindow); // if feed is null, then that means no calendar items changed for the user since we last queried. if (feed == null) { log.DebugFormat( "Calendar has not changed for user {0}. User will not be synced this round.", login); continue; } if (!ValidateFeed(feed)) { /* No Google App Feed was returned, skip to next user */ log.WarnFormat( "GCal feed could not be read for '{0}'. This user may not have activated their account or may be inactive." + "For resources the admin must share their calendars for the domain and set correctly the timezone.", login); continue; } log.InfoFormat("Calendar Query returned {0} events", feed.Entries.Count); using (BlockTimer freeBusyTimer = new BlockTimer("WriteFreeBusy")) { /* User and feed retrieval was succesful, merge the two datasources down into Exchange */ freeBusyWriter.SyncUser(user, feed, exchangeGateway, syncWindow); } // Only update the modified time if we sync'd modifiedDateUtil.UpdateUserModifiedTime(login, currentDate); } catch (Exception ex) { Interlocked.Increment(ref errorCount); log.Error(string.Format( "Error occured while executing sync process for user '{0}'. [running error count={1}]", login, errorCount), ex); } if (errorCount > errorThreshold) { throw new GCalExchangeException( GCalExchangeErrorCode.GenericError, "Error threshold has been surpassed, aborting sync process."); } } log.InfoFormat("User synchronization complete. {0} users processed.", userCount); }
/// <summary> /// Run the sync process from Google Calendar to Exchange /// </summary> /// <param name="threadCount">Number of threads to use to sync</param> public void RunSyncProcess(int threadCount) { log.Info("Exchange synchronization process started."); using (BlockTimer bt = new BlockTimer("RunSyncProcess")) { gcalGateway = new GCalGateway(googleAppsLogin, googleAppsPassword, googleAppsDomain, null); exchangeGateway = new ExchangeService(exchangeServer, networkLogin, networkPassword); ExchangeUserDict users; using (BlockTimer loadUserTimer = new BlockTimer("LoadUserList")) { users = QueryExchangeForValidUsers(); } exchangeUsers = new List <ExchangeUser>(); freeBusyWriter = FreeBusyWriterFactory.GetWriter(exchangeUsers); foreach (ExchangeUser user in users.Values) { exchangeUsers.Add(user); } if (exchangeUsers.Count == 0) { log.Warn("No eligible users found for synchronization. Aborting sync process."); return; } if (threadCount < 1) { threadCount = 1; } modifiedDateUtil = new ModifiedDateUtil(ConfigCache.ServiceModifiedXmlFileName); modifiedDateUtil.LoadModifiedTimes(); if (threadCount == 1) { SyncUsers(); } else { StartSyncUserThreads(threadCount); } modifiedDateUtil.PersistModifiedTimes(); gcalGateway = null; exchangeGateway = null; freeBusyWriter = null; modifiedDateUtil = null; exchangeUsers = null; System.GC.Collect(); log.DebugFormat("Memory after sync: {0}", System.GC.GetTotalMemory(false)); } }
public static void test_reduce_profiling() { LocalProfiler p = new LocalProfiler(); p.Start("load"); //DMesh3 mesh = TestUtil.LoadTestMesh("c:\\scratch\\bunny_solid.obj"); //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\scratch\\current_test\\g3sharp_user_OBJ\\OBJ\\dizhi.obj"); //DMesh3 mesh = TestUtil.LoadTestMesh("C:\\scratch\\current_test\\g3sharp_user_OBJ\\exported.obj"); //DMesh3 mesh = TestUtil.LoadTestMesh("c:\\scratch\\bunny_open.obj"); DMesh3 loadMesh = TestUtil.LoadTestMesh("c:\\scratch\\ZentrigDoo_Hires_Upper.stl"); System.Console.WriteLine("Loaded..."); p.StopAllAndStartNew("check"); //mesh.CheckValidity(); System.Console.WriteLine("Checked..."); double time_ticks = 0; int Niters = 10; DMesh3 mesh = null; for (int k = 0; k < Niters; ++k) { mesh = new DMesh3(loadMesh); int N = 100000; System.Console.WriteLine("Reducing from {0} to {1}...", mesh.TriangleCount, N); BlockTimer reduceT = p.StopAllAndStartNew("reduce"); Reducer r = new Reducer(mesh); //r.MinimizeQuadricPositionError = false; r.ENABLE_PROFILING = true; //DMeshAABBTree3 tree = new DMeshAABBTree3(new DMesh3(mesh)); //tree.Build(); //MeshProjectionTarget target = new MeshProjectionTarget(tree.Mesh, tree); //r.SetProjectionTarget(target); //r.ProjectionMode = Reducer.TargetProjectionMode.Inline; //r.SetExternalConstraints(new MeshConstraints()); ////MeshConstraintUtil.PreserveBoundaryLoops(r.Constraints, mesh); //MeshConstraintUtil.FixAllBoundaryEdges(r.Constraints, mesh); r.ReduceToTriangleCount(N); //double min, max, avg; //MeshQueries.EdgeLengthStats(mesh, out min, out max, out avg); //r.ReduceToEdgeLength(avg * 1.5); //System.Console.WriteLine("Reduced..."); p.Stop("reduce"); time_ticks += reduceT.Watch.Elapsed.Ticks; System.Console.WriteLine(p.AllTimes()); GC.Collect(); } TimeSpan total = new TimeSpan((int)(time_ticks / (double)Niters)); System.Console.WriteLine("AVERAGE: {0}", string.Format("{0:ss}.{0:ffffff}", total)); TestUtil.WriteDebugMesh(mesh, "__REDUCED.obj"); }
/// <summary> /// Combines the free busy and appointment blocks supplied to the exchange user object /// If no appointments are supplied the user will still have free busy time blocks assigned /// to them, with a null appointment assigned to the free busy time. /// </summary> /// <param name="exchangeUser">Exchange users to apply freeBusy and appointments</param> /// <param name="freeBusy">The collection of FreeBusy blocks to assign to exchangeUser</param> /// <param name="appointments">The collection of appointment blocks to assign to exchangeUser</param> /// <param name="window">Window to merge for</param> protected void MergeFreeBusyWithAppointments( ExchangeUser exchangeUser, FreeBusy freeBusy, List <Appointment> appointments, DateTimeRange window) { using (BlockTimer bt = new BlockTimer("MergeFreeBusyWithAppointments")) { IntervalTree <FreeBusyTimeBlock> busyIntervals = new IntervalTree <FreeBusyTimeBlock>(); FreeBusyCollection busyTimes = new FreeBusyCollection(); int appointmentsCount = 0; List <DateTimeRange> combinedTimes = FreeBusyConverter.MergeFreeBusyLists(freeBusy.All, freeBusy.Tentative); /* Add the date ranges from each collection in the FreeBusy object */ ConvertFreeBusyToBlocks(window, combinedTimes, busyTimes, busyIntervals); if (appointments != null && appointments.Count > 0) { appointmentsCount = appointments.Count; foreach (Appointment appt in appointments) { log.DebugFormat("Appt \"{0}\" {1} {2} response = {3} status = {4} busy = {5}", appt.Subject, appt.Range, appt.StartDate.Kind, appt.ResponseStatus, appt.MeetingStatus, appt.BusyStatus); if (appt.BusyStatus == BusyStatus.Free) { continue; } DateTimeRange range = new DateTimeRange(appt.StartDate, appt.EndDate); List <FreeBusyTimeBlock> result = busyIntervals.FindAll(range, IntervalTreeMatch.Overlap); log.DebugFormat("Found {0} ranges overlap {1}", result.Count, range); foreach (FreeBusyTimeBlock block in result) { log.DebugFormat("Adding \"{0}\" to FB {1} {2}", appt.Subject, block.Range, block.StartDate.Kind); block.Appointments.Add(appt); } busyTimes.Appointments.Add(appt); } } foreach (FreeBusyTimeBlock block in busyTimes.Values) { block.Appointments.Sort(CompareAppointmentsByRanges); } log.InfoFormat("Merge Result of {0} + Appointment {1} -> {2}", combinedTimes.Count, appointmentsCount, busyTimes.Count); /* Assign the data structure to the exchange user */ exchangeUser.BusyTimes = busyTimes; } }