/// <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); }