public FetchPayload OpenStream() { var retRec = new FetchPayload(); var filter = Builders <BakedVolumes> .Filter.Eq("_id", Volume); VolumeRec = Bvs.FindSync(filter).FirstOrDefault(); if (VolumeRec == null) { retRec.Error = $"Volume: {Volume} does not exist"; return(retRec); } if (!VolumeRec.Parts.ContainsKey(Part)) { retRec.Error = $"Volume: {Volume} Part {Part} does not exist"; return(retRec); } var p = VolumeRec.Parts[Part]; fName = Path.Combine(p.Path, p.Name); try { binOpen = new BinaryReader(File.Open(fName, FileMode.Open, FileAccess.Read)); VolumeStream = binOpen.BaseStream; } catch (Exception ex) { retRec.Error = ex.Message; if (logger != null) { logger.LogError(ex, $"Cannot open file {fName} for {Volume}/{Part}"); } return(retRec); } //Console.WriteLine($"[Open Volume: {fName}]"); return(retRec); }
public FetchPayload GetRecord(FetchRequest request) { var volume = request.BakedVolume; var part = request.Part; if (bvs == null) { bvs = NeoMongo.NeoDb.BakedVolumes(); } var cacheKey = volume + "/" + part; VolCacheRec cache; if (!openFileCache.TryGetValue <VolCacheRec>(cacheKey, out cache)) { cache = new VolCacheRec(bvs, volume, part, _logger); } openFileCache.Set <VolCacheRec>(cacheKey, cache); // Our caches work, but we're not really managing any kind of residency. // We'll play with this and see how they work, but it's trivial to // simply DDOS the cache into insanity. // We're also not handling error retry, though that may not be our job. // We may have to make some specific errors flow back so the client can // deal with a moved file or a service down. It theoretically can even // use the X file if one of the main 4 is not available to regen the // data flow with XOR (in degraded mode). This service will read any part. var retRec = new FetchPayload(); retRec.Error = String.Empty; if (cache.VolumeStream == null) { retRec = cache.OpenStream(); } if (retRec.Error != String.Empty) { Console.WriteLine($"? Encountered error: {retRec.Error}"); return(retRec); } // Now if the file is gone/moved we might get an error seeking var didSeek = cache.VolumeStream.Seek(request.Offset, SeekOrigin.Begin); var length = Math.Min(BUFSIZ, request.RequestCount); var count = cache.VolumeStream.Read(buffer, 0, length); retRec.Length = count; // Not sure what's efficient here - nice if we didn't have to copy retRec.Payload = ByteString.CopyFrom(buffer, 0, count); Console.WriteLine($"[Read: {request.BakedVolume}/{request.Part} Count={count} Offset={request.Offset} (actual={didSeek}, newpos={cache.VolumeStream.Position})"); return(retRec); }