Ejemplo n.º 1
0
        public async Task DurableCache_EventsAreSavedAndRestored()
        {
            // Create a test event to add to the cache
            var testEvent = new CachedEvent("CollectionName", JObject.FromObject(new { Property = "Value" }));

            // Create the cache to be tested
            var cache = await EventCachePortableTestable.NewTestableAsync();

            // Add the event to the cache
            await cache.AddAsync(testEvent);

            // Destroy the cache object and clear the static event queue
            cache.ResetStaticMembers();
            cache = null;

            // The event should have been written to disk, and creating a new cache should populate
            // from disk
            var newCache = await EventCachePortableTestable.NewTestableAsync();

            var actualEvent = await newCache.TryTakeAsync();

            // Event read should be equal to the original
            Assert.NotNull(actualEvent);
            Assert.AreEqual(testEvent.Event, actualEvent.Event);
            Assert.AreEqual(testEvent.Collection, actualEvent.Collection);
            Assert.AreEqual(testEvent.Error, actualEvent.Error);

            // Shouldn't be more events stored
            Assert.Null(await newCache.TryTakeAsync());
        }
Ejemplo n.º 2
0
        public async Task <CachedEvent> TryTake()
        {
            var keenFolder = await getKeenFolder()
                             .ConfigureAwait(continueOnCapturedContext: false);

            if (!events.Any())
            {
                return(null);
            }

            string fileName;

            lock (events)
                fileName = events.Dequeue();

            var file = await keenFolder.GetFileAsync(fileName)
                       .ConfigureAwait(continueOnCapturedContext: false);

            var content = await file.ReadAllTextAsync()
                          .ConfigureAwait(continueOnCapturedContext: false);

            dynamic ce = JObject.Parse(content);

            var item = new CachedEvent((string)ce.Collection, (JObject)ce.Event, (Exception)ce.Error);
            await file.DeleteAsync()
            .ConfigureAwait(continueOnCapturedContext: false);

            return(item);
        }
Ejemplo n.º 3
0
        public ActionResult ViewImage(int id, long? @event, long?user)
        {
            CachedEvent viewEvent = null;

            if (@event.HasValue)
            {
                viewEvent = this.Events.GetEvent(@event.Value);

                if (viewEvent == null)
                {
                    return(this.HttpError(404, this.View("NotFound")));
                }
            }

            UserInformation viewUser = null;

            if (user.HasValue)
            {
                viewUser = this.Users.GetUserInformation(user.Value);

                if (viewUser == null)
                {
                    return(this.HttpError(404, this.View("NotFound")));
                }
            }

            var images     = FilterImages(this.Db.EventImages, @event, user);
            var imageCount = images.Count();

            if (imageCount == 0)
            {
                return(this.HttpError(404, this.View("NotFound")));
            }

            var viewImages = images.ToList();

            id = Math.Max(1, Math.Min(imageCount, id));
            var viewImage = viewImages.Skip(id - 1).Take(1).SingleOrDefault();

            var tags = (from t in this.Db.EventImageUserTags
                        where t.EventImageId == viewImage.EventImageID
                        select new UserTag
            {
                UserId = t.TaggedUserUserId,
                Username = t.TaggedUser.Username,
                TagRegion = t.RegionGeometry
            }).ToList();

            return(this.View(new ViewImageModel
            {
                Event = viewEvent,
                User = viewUser,
                Image = viewImage,
                Images = viewImages,
                UserTags = tags,
                AllowTagging = this.Security.IsUserAdministrator(this.CurrentUser)
            }));
        }
Ejemplo n.º 4
0
        public ActionResult Gallery(long? @event, long?user, int?page)
        {
            int pageSize = 50;

            CachedEvent viewEvent = null;

            if (@event.HasValue)
            {
                viewEvent = this.Events.GetEvent(@event.Value);

                if (viewEvent == null)
                {
                    return(this.HttpError(404, this.View("NotFound")));
                }
            }

            UserInformation viewUser = null;

            if (user.HasValue)
            {
                viewUser = this.Users.GetUserInformation(user.Value);

                if (viewUser == null)
                {
                    return(this.HttpError(404, this.View("NotFound")));
                }
            }

            var images = FilterImages(this.Db.EventImages, @event, user);

            int imageCount = images.Count();
            int pages      = Pager.PageCount(imageCount, pageSize);

            page = Pager.ClampPage(page, pages);

            var viewImages = images.Skip((page.Value - 1) * pageSize).Take(pageSize).ToList();

            return(this.View(new ImageGalleryModel
            {
                Event = viewEvent,
                User = viewUser,
                Images = viewImages,
                PageInfo = new PaginationInformation
                {
                    Pager = this.Skins.GetDefaultGalleryPager(),
                    CurrentPage = page,
                    Items = imageCount,
                    ItemsPerPage = pageSize,
                    ControllerName = "Images",
                    ActionName = "Gallery",
                    PageAttribute = "page",
                    RouteValues = new System.Web.Routing.RouteValueDictionary(new { @event = @event, user = user })
                }
            }));
        }
Ejemplo n.º 5
0
        public Task Add(CachedEvent e)
        {
            if (null == e)
                throw new KeenException("Cached events may not be null");

            return Task.Run(() =>
            {
                lock (events)
                    events.Enqueue(e);
            });
        }
Ejemplo n.º 6
0
        public async Task <CachedEvent> TryTakeAsync()
        {
            if (!events.Any())
            {
                return(null);
            }

            string fileName;

            lock (events)
            {
                // Get the file name of the first event in the queue
                fileName = events.First();
            }

            string fullFileName = Path.Combine(GetKeenFolderPath(), fileName);

            CachedEvent item;

            try
            {
                string content;
                using (FileStream stream = File.Open(fullFileName, FileMode.Open))
                {
                    byte[] fileBytes = new byte[stream.Length];
                    await stream.ReadAsync(fileBytes, 0, (int)stream.Length);

                    content = Encoding.UTF8.GetString(fileBytes);
                }

                var ce = JObject.Parse(content);

                item = new CachedEvent(
                    (string)ce.SelectToken("Collection"),
                    (JObject)ce.SelectToken("Event"),
                    ce.SelectToken("Error").ToObject <Exception>());

                await Task.Run(() => File.Delete(fullFileName))
                .ConfigureAwait(continueOnCapturedContext: false);
            }
            finally
            {
                lock (events)
                {
                    // Dequeue the event now that we're done with it
                    events.Dequeue();
                }
            }

            return(item);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Adds an event to the cache.
        /// </summary>
        /// <returns></returns>
        /// <param name="e">The CachedEvent to add to the cache.</param>
        public async Task AddAsync(CachedEvent e)
        {
            if (null == e)
            {
                throw new KeenException("Cached events may not be null");
            }

            // Get/create the cache directory
            DirectoryInfo keenFolder = await GetOrCreateKeenDirectoryAsync()
                                       .ConfigureAwait(continueOnCapturedContext: false);

            // Come up with a name to use for the file on disk.
            // This is sufficiently random such that name collisions
            // won't happen.
            string fileName = Path.GetRandomFileName();

            lock (events)
            {
                events.Enqueue(fileName);
            }

            try
            {
                var content = JObject.FromObject(e).ToString();

                using (FileStream stream = File.Open(Path.Combine(keenFolder.FullName, fileName),
                                                     FileMode.CreateNew))
                {
                    byte[] fileBytes = Encoding.UTF8.GetBytes(content);
                    await stream.WriteAsync(fileBytes, 0, fileBytes.Length);
                }
            }
            catch (Exception ex)
            {
                throw new KeenException("Failure while saving file", ex);
            }
        }
Ejemplo n.º 8
0
        public async Task Add(CachedEvent e)
        {
            if (null == e)
            {
                throw new KeenException("Cached events may not be null");
            }

            var keenFolder = await getKeenFolder()
                             .ConfigureAwait(continueOnCapturedContext: false);

            IFile  file;
            var    attempts = 0;
            var    done     = false;
            string name     = null;

            do
            {
                attempts++;

                // Avoid race conditions in parallel environment by locking on the events queue
                // and generating and inserting a unique name within the lock. CreateFileAsync has
                // a CreateCollisionOption.GenerateUniqueName, but it will return the same name
                // multiple times when called from parallel tasks.
                // If creating and writing the file fails, loop around and
                if (string.IsNullOrEmpty(name))
                {
                    lock (events)
                    {
                        var i = 0;
                        while (events.Contains(name = e.Collection + i++))
                        {
                            ;
                        }
                        events.Enqueue(name);
                    }
                }

                Exception lastErr = null;
                try
                {
                    file = await keenFolder.CreateFileAsync(name, CreationCollisionOption.FailIfExists)
                           .ConfigureAwait(continueOnCapturedContext: false);

                    var content = JObject.FromObject(e).ToString();

                    await file.WriteAllTextAsync(content)
                    .ConfigureAwait(continueOnCapturedContext: false);

                    done = true;
                }
                catch (Exception ex)
                {
                    lastErr = ex;
                }

                // If the file was not created, not written, or partially written,
                // the events queue may be left with a file name that references a
                // file that is nonexistent, empty, or invalid. It's easier to handle
                // this when the queue is read than to try to dequeue the name.
                if (attempts > 100)
                {
                    throw new KeenException("Persistent failure while saving file, aborting", lastErr);
                }
            } while (!done);
        }