Beispiel #1
0
        /// <summary>
        /// Callback when slave receives MessageIoFlowUpdate.
        /// Typically one of these messages updates a batch of flows.
        /// This is a request from the Rate Controller to update state for the given flows.
        /// </summary>
        /// <param name="listParams"></param>
        /// <returns></returns>
        public OktoResultCodes CallbackMessageIoFlowUpdate(List <IoFlowMessageParams> listParams)
        {
            lock (LockFlows)
            {
                foreach (IoFlowMessageParams flowu in listParams)
                {
                    IoFlow flow = DictIoFlow[flowu.FlowId];

                    parseControllerCommandString(flow, flowu.ParameterString);
                }
            }
            return(OktoResultCodes.OKTO_RESULT_SUCCESS);
        }
Beispiel #2
0
        /// <summary>
        /// Callback when slave receives MessageIoFlowStatsQuery.
        /// The reply message generated herein provides stats for all flows of the current tenant.
        /// This is a request from Rate Controller to return stats for all flows for current tenant.
        /// </summary>
        /// <returns></returns>
        public List <IoFlowMessageParams> CallbackMessageIoFlowStatsQuery()
        {
            //Console.WriteLine("CallbackMessageIoFlowStatsQuery()");
            List <IoFlowMessageParams> listStats = new List <IoFlowMessageParams>();

            lock (LockFlows)
            {
                foreach (IoFlowMessageParams statsquery in DictFlowCreateParams.Values)
                {
                    IoFlow flow = DictIoFlow[statsquery.FlowId];
                    listStats.Add(new IoFlowMessageParams(flow.FlowId, formatCacheStatsString(flow.FlowId), (byte)flow.Flags));
                }
            }
            return(listStats);
        }
Beispiel #3
0
        public LinkedListNode <FileCacheElement> nodeInFreeFileCacheList; // location in free file cache element linked list

        //
        // Constructor.
        // Copies InData locally
        public FileCacheElement(IoFlow InFlow, string InFileName, byte[] InData, UInt64 InFileOffset, uint copyOffset, uint InDataLength)
        {
            LockObj                 = new object();
            fileName                = InFileName;
            Flow                    = InFlow;
            Data                    = null;
            FileOffset              = InFileOffset;
            DataLength              = InDataLength;
            Dirty                   = false;
            nodeInList              = null;
            nodeInDirtyList         = null;
            nodeInFreeFileCacheList = null;
            if (InData != null)
            {
                Data = new byte[InDataLength];
                Buffer.BlockCopy(InData, (int)copyOffset, Data, 0, (int)InDataLength);
                //Array.Copy(InData, copyOffset, Data, 0, InDataLength);
            }
        }
Beispiel #4
0
        private FileCacheElement getFileCacheElement(IoFlow InFlow, string InFileName, byte[] InData, UInt64 InFileOffset, uint copyOffset, uint InDataLength)
        {
            FileCacheElement elemReturn;
            bool             reused = false;

            lock (this.freeFileCacheElements)
            {
                if (this.freeFileCacheElements.Count > 0)
                {
                    LinkedListNode <FileCacheElement> llNode = this.freeFileCacheElements.First;
                    this.freeFileCacheElements.Remove(llNode);
                    elemReturn = llNode.Value;
                    reused     = true;
                }
                else
                {
                    elemReturn = new FileCacheElement(InFlow, InFileName, InData, InFileOffset, copyOffset, InDataLength);
                }
            }
            if (reused)
            {
                Debug.Assert(elemReturn.DataLength == InDataLength);
                elemReturn.fileName = InFileName;
                elemReturn.Flow     = InFlow;
                // keep data elemReturn.Data = null;
                elemReturn.FileOffset      = InFileOffset;
                elemReturn.DataLength      = InDataLength;
                elemReturn.Dirty           = false;
                elemReturn.nodeInList      = null;
                elemReturn.nodeInDirtyList = null;
                if (InData != null)
                {
                    Buffer.BlockCopy(InData, (int)copyOffset, elemReturn.Data, 0, (int)InDataLength);
                }
            }
            return(elemReturn);
        }
Beispiel #5
0
        /// <summary>
        /// Callback when slave has received all create parameters for flows and raps from rate controller.
        /// This is a request from the Rate Controller to configure IoFlow diver state for current tenant.
        /// </summary>
        /// <param name="dictFlowParams">Flow create params keyed on FlowId.</param>
        /// <param name="dictRapParams">RAP create params keyed on FlowId.</param>
        /// <returns></returns>
        public OktoResultCodes CallbackIoFlowCreate(
            Dictionary <uint, IoFlowMessageParams> dictFlowParams,
            Dictionary <uint, MsgRapArg> dictRapParams)
        {
            lock (LockFlows)
            {
                DictFlowCreateParams = dictFlowParams;
                DictRapCreateParams  = dictRapParams;
                foreach (uint flowId in DictFlowCreateParams.Keys)
                {
                    IoFlowMessageParams flowc      = DictFlowCreateParams[flowId];
                    MsgRapArg           rapc       = DictRapCreateParams[flowId];
                    string[]            separators = new string[] { " ", "\t" };
                    string[]            toks       = flowc.ParameterString.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                    string vmName              = toks[1];
                    string volumeName          = toks[4];
                    UInt64 flowCacheSize       = Convert.ToUInt64(toks[5]);
                    UInt32 ghostCacheBlockSize = Convert.ToUInt32(toks[6]);
                    string writePolicy         = toks[7];
                    string writeCachePolicy    = toks[8];
                    UInt64 fileCacheTotalSize  = Convert.ToUInt64(toks[9]);

                    if (cache == null) //Create a file cache when we get the first request for a flow create
                    {
                        this.cache = new FileCache(fileCacheTotalSize, noisyOutput);
                    }

                    string thisMachine  = System.Environment.MachineName.ToLower();
                    string ctrlFileName = rapc.ShareOrVolume;
                    string ctrlHostName = null;
                    string fileName     = null;

                    if (ctrlFileName.Substring(0, 2).Equals(@"\\"))
                    {
                        ctrlHostName = ctrlFileName.Substring(2);
                    }
                    else if (ctrlFileName.Substring(0, 1).Equals(@"\"))
                    {
                        ctrlHostName = ctrlFileName.Substring(1);
                    }
                    else
                    {
                        Debug.Assert(0 == 1); //all strings from the controller should start like that
                    }
                    int    idxEndHostName = ctrlHostName.IndexOf(@"\");
                    string shareFile      = ctrlHostName.Substring(idxEndHostName);
                    ctrlHostName = ctrlHostName.Substring(0, idxEndHostName);

                    if (ctrlHostName.Equals(thisMachine))
                    {
                        fileName = this.runtime.getDriveLetterFileName(volumeName + shareFile);
                    }
                    else
                    {
                        fileName = ctrlFileName;
                    }

                    // Params look reasonable and FlowCreate and RapCreate match up: create the IoFlow here.

                    IoFlow f1 = runtime.CreateFlow(flowId, vmName, fileName, PreCreate, null, PreRead, PostRead, PreWrite, PostWrite, PreCleanup, null, null, null);

                    //Set the remaining init parameters that are also dynamically change-able
                    cache.CacheSetFlowSize(flowId, flowCacheSize);
#if USE_GHOST_CACHE
                    cache.CacheCreateGhostCache(f1.FlowId, ghostCacheBlockSize);
#endif
                    switch (writePolicy)
                    {
                    case "write-through":
                        cache.SetCacheWritePolicy(CacheWritePolicy.WriteThrough);
                        break;
                    }
                    switch (writeCachePolicy)
                    {
                    case "CacheWrites":
                        cache.SetCacheWriteBuffering(CacheWriteBuffer.Cache);
                        break;

                    case "noCacheWrites":
                        cache.SetCacheWriteBuffering(CacheWriteBuffer.noCache);
                        break;
                    }


                    DictIoFlow.Add(flowc.FlowId, f1);
                }
            }
            return(OktoResultCodes.OKTO_RESULT_SUCCESS);
        }
Beispiel #6
0
        private void parseControllerCommandString(IoFlow flow, string controllerCommand)
        {
            string[] commandStringSeparators = new string[] { " ", "\t" };
            char[]   tokenSeparator          = new char[] { '=' };
            string[] commandTokens           = controllerCommand.Split(commandStringSeparators, StringSplitOptions.RemoveEmptyEntries);

            if (commandTokens.Length > 0)
            {
                Console.WriteLine("CallbackMessageIoFlowUpdate({0},{1})", flow.FlowId, controllerCommand);
                foreach (string token in commandTokens)
                {
                    string param = token.Split(tokenSeparator)[0];
                    string value = token.Split(tokenSeparator)[1];


                    //Switch to the appropriate handler
                    switch (param)
                    {
                    case "changeCacheSize":
                        this.cache.CacheSetFlowSize(flow.FlowId, Convert.ToUInt64(value));
                        break;

                    case "changeWritePolicy":
                        switch (value)
                        {
                        case "write-through":
                            this.cache.SetCacheWritePolicy(CacheWritePolicy.WriteThrough);
                            break;

                        default:
                            Console.WriteLine("Command value invalid");
                            Debug.Assert(0 == 1);
                            break;
                        }
                        break;

                    case "changeOpPolicy":
                        string op     = value.Split(',')[0];
                        string policy = value.Split(',')[1];
                        switch (op)
                        {
                        case "W":
                            switch (policy)
                            {
                            case "yes":
                                this.cache.SetCacheWriteBuffering(CacheWriteBuffer.Cache);             //Cache writes
                                break;

                            case "no":
                                this.cache.SetCacheWriteBuffering(CacheWriteBuffer.noCache);             //Don't cache writes
                                break;

                            default:
                                Console.WriteLine("Command value invalid");
                                Debug.Assert(0 == 1);
                                break;
                            }
                            break;

                        case "R":
                            //Nothing for now; add fine-grained control to cache/not cache reads here
                            break;

                        default:
                            Console.WriteLine("Command value invalid");
                            Debug.Assert(0 == 1);
                            break;
                        }
                        break;

                    default:
                        Console.WriteLine("Controller command invalid");
                        Debug.Assert(0 == 1);
                        break;
                    }
                }
            }
        }
Beispiel #7
0
        public bool Start()
        {
            string thisMachine = System.Environment.MachineName.ToLower();

            //
            // Initialize IoFlow runtime.
            //
            IoFlowRuntime runtime = new IoFlowRuntime((uint)Mpl);

            string line;

            // get info from config file
            Debug.Assert(inputConfig != null && File.Exists(inputConfig));
            string[] separators      = new string[] { " ", "\t" };
            System.IO.StreamReader f = new System.IO.StreamReader(inputConfig);

            // line has entries SRV_NAME, VM_NAME, VHD_NAME, cacheSizeMB, IO_req_size, write-back/write-through, noCacheWrites/cacheWrites
            while ((line = f.ReadLine()) != null)
            {
                string[] tokens = line.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                if (tokens.Length == 0)
                {
                    continue;
                }
                else if (tokens[0].StartsWith(@"#") || tokens[0].StartsWith(@"//"))
                {
                    continue;
                }
                if (tokens.Length < 7)
                {
                    throw new ApplicationException(String.Format("invalid config file"));
                }
                if (!(tokens[5].Equals("write-through") || tokens[5].Equals("write-back")))
                {
                    throw new ApplicationException(String.Format("invalid config file"));
                }
                if (!(tokens[6].Equals("cacheWrites") || tokens[6].Equals("noCacheWrites")))
                {
                    throw new ApplicationException(String.Format("invalid config file"));
                }

                Console.WriteLine("Got tokens {0}, {1}, {2}, {3}, {4}, {5}, {6}", tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5], tokens[6]);


                if (thisMachine.StartsWith(tokens[0].ToLower()))
                {
                    IoFlow f1 = runtime.CreateFlow(runtime.GetNextFreeFlowId(), tokens[1].ToLower(), tokens[2].ToLower(), PreCreate, null, PreRead, PostRead, PreWrite, PostWrite, PreCleanup, null, null, null);
                    cache.CacheSetFlowSize(f1.FlowId, Convert.ToUInt64(tokens[3]));

                    //cache.CacheCreateGhostCache(f1.FlowId, Convert.ToUInt32(tokens[4])); //XXXIS: this should come from the controller...
                    cache.AlignedBlockSize = Convert.ToUInt32(tokens[4]);

                    switch (tokens[5])
                    {
                    case "write-through":
                        cache.SetCacheWritePolicy(CacheWritePolicy.WriteThrough);
                        break;
                    }

                    switch (tokens[6])
                    {
                    case "cacheWrites":
                        cache.SetCacheWriteBuffering(CacheWriteBuffer.Cache);
                        break;

                    case "noCacheWrites":
                        cache.SetCacheWriteBuffering(CacheWriteBuffer.noCache);
                        break;
                    }
                }
            }


            runtime.Start(false);

            CacheThreadBlocked.WaitOne();
            runtime.Close();
            return(true);
        }