// ----------------------------------------------------------------------------
//
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ----------------------------------------------------------------------------

using System;
using System.Collections;
using System.Text;

namespace Singularity.Application.SPECWeb99.WebFiles
{
    class Cache
    {
        private const bool verbose = false;
        private UrlSet cache;
        private UrlSet free;
        private int size;

        public Cache(int cacheSize, int deckSize)
        {
            cache = new UrlSet(cacheSize);
            free = new UrlSet(deckSize);
            this.size = cacheSize;
        }

        public FileSpec GetUrl(Client/*!*/ client, int id) {
            // first check the local cache
            // then see if anyone else is generating the  global

            if (cache.pos > 0) {
                return cache.urls[--cache.pos];
            }

            // return local free to global free pool

            client.globalLock.WaitOne();
            while (free.pos > 0) {
                if (client.freeDeck.pos >= client.freeDeck.urls.Length) {
                    //Console.WriteLine(" too many free slots!");
                    free.urls[--free.pos] = null;
                    //DebugStub.Break();
                    free.pos--;
                }
                else {
                    client.freeDeck.urls[client.freeDeck.pos++] =
                        free.urls[--free.pos];
                }
            }

            // now see if there are any urls available
            // if not either wait on or generate the global deck

            while (client.urlDeck.pos == 0) {
                if (client.generatingUrls == false) {
                    //Console.WriteLine("Generating cache");
                    UrlSet temp = client.urlDeck;
                    client.urlDeck = client.spareDeck;
                    client.spareDeck = temp;
                    client.generatingUrls = true;
                    client.syncLock.WaitOne();
                    client.globalLock.ReleaseMutex();
                    client.GenerateFileSpecs();
                    client.globalLock.WaitOne();
                    client.generatingUrls = false;
                    client.syncLock.ReleaseMutex();
                }
                else {
                    //Console.WriteLine("Waiting for cache");
                    client.globalLock.ReleaseMutex();
                    client.syncLock.WaitOne();
                    client.syncLock.ReleaseMutex();
                    client.globalLock.WaitOne();
                }
            }

            // the global deck is ok -- prime our cache

            if (client.urlDeck.pos > 0) {
                for (int i = 0; i < cache.urls.Length && (client.urlDeck.pos > 0); i++) {
                    cache.urls[cache.pos++] =
                        client.urlDeck.urls[--client.urlDeck.pos];
                }
            }
            client.globalLock.ReleaseMutex();
            return cache.urls[--cache.pos];
        }

        public void FreeUrl(FileSpec url) {
            if (free.pos + 1 >= free.urls.Length) {
                //Console.WriteLine("free cache full! de-allocating");
                url = null;
                return;
            }
            free.urls[free.pos++] = url;
        }
    }
}
