예제 #1
0
        public void Add(SmapsReaderResults results)
        {
            var djv = new DynamicJsonValue
            {
                ["File"]              = results.ResultString,
                ["Size"]              = Sizes.Humane(results.Size),
                ["Rss"]               = Sizes.Humane(results.Rss),
                ["SharedClean"]       = Sizes.Humane(results.SharedClean),
                ["SharedDirty"]       = Sizes.Humane(results.SharedDirty),
                ["PrivateClean"]      = Sizes.Humane(results.PrivateClean),
                ["PrivateDirty"]      = Sizes.Humane(results.PrivateDirty),
                ["TotalClean"]        = results.SharedClean + results.PrivateClean,
                ["TotalCleanHumanly"] = Sizes.Humane(results.SharedClean + results.PrivateClean),
                ["TotalDirty"]        = results.SharedDirty + results.PrivateDirty,
                ["TotalDirtyHumanly"] = Sizes.Humane(results.SharedDirty + results.PrivateDirty),
                ["TotalSwap"]         = results.Swap,
                ["TotalSwapHumanly"]  = Sizes.Humane(results.Swap)
            };

            if (_dja == null)
            {
                _dja = new DynamicJsonArray();
            }
            _dja.Add(djv);
        }
예제 #2
0
        public Task GetDocSize()
        {
            var id = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    var document = Database.DocumentsStorage.GetDocumentMetrics(context, id);
                    if (document == null)
                    {
                        HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                        return(Task.CompletedTask);
                    }

                    HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;

                    var documentSizeDetails = new DocumentSizeDetails
                    {
                        DocId               = id,
                        ActualSize          = document.Value.ActualSize,
                        HumaneActualSize    = Sizes.Humane(document.Value.ActualSize),
                        AllocatedSize       = document.Value.AllocatedSize,
                        HumaneAllocatedSize = Sizes.Humane(document.Value.AllocatedSize)
                    };

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        context.Write(writer, documentSizeDetails.ToJson());
                        writer.Flush();
                    }

                    return(Task.CompletedTask);
                }
        }
예제 #3
0
 public DiskFullException(string filePath, long requestedFileSize, long?freeSpace)
     : base(
         $"There is not enough space for file {filePath} to {Sizes.Humane(requestedFileSize)}. " +
         $"Currently available space: {Sizes.Humane(freeSpace)}"
         )
 {
     DirectoryPath    = Path.GetDirectoryName(filePath);
     CurrentFreeSpace = freeSpace ?? requestedFileSize - 1;
 }
예제 #4
0
 public DiskFullException(string filePath, long requestedFileSize, long?freeSpace, string msg)
     : base(
         $"There is not enough space to set the size of file {filePath} to {Sizes.Humane(requestedFileSize)}. " +
         $"Currently available space: {Sizes.Humane(freeSpace) ?? "N/A"}. Error Message: {msg}"
         )
 {
     DirectoryPath    = Path.GetDirectoryName(filePath);
     CurrentFreeSpace = freeSpace ?? requestedFileSize - 1;
 }
예제 #5
0
        public Task MemorySmaps()
        {
            if (PlatformDetails.RunningOnLinux == false)
            {
                using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
                {
                    var rc  = Win32MemoryQueryMethods.GetMaps();
                    var djv = new DynamicJsonValue
                    {
                        ["Totals"] = new DynamicJsonValue
                        {
                            ["WorkingSet"]          = rc.WorkingSet,
                            ["SharedClean"]         = "N/A",
                            ["PrivateClean"]        = "N/A",
                            ["TotalClean"]          = rc.ProcessClean,
                            ["RssHumanly"]          = Sizes.Humane(rc.WorkingSet),
                            ["SharedCleanHumanly"]  = "N/A",
                            ["PrivateCleanHumanly"] = "N/A",
                            ["TotalCleanHumanly"]   = Sizes.Humane(rc.ProcessClean)
                        },
                        ["Details"] = rc.Json
                    };
                    using (var write = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        context.Write(write, djv);
                    }
                    return(Task.CompletedTask);
                }
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
            {
                var result = new SmapsReader().CalculateMemUsageFromSmaps();
                var djv    = new DynamicJsonValue
                {
                    ["Totals"] = new DynamicJsonValue
                    {
                        ["WorkingSet"]          = result.Rss,
                        ["SharedClean"]         = result.SharedClean,
                        ["PrivateClean"]        = result.PrivateClean,
                        ["TotalClean"]          = result.SharedClean + result.PrivateClean,
                        ["RssHumanly"]          = Sizes.Humane(result.Rss),
                        ["SharedCleanHumanly"]  = Sizes.Humane(result.SharedClean),
                        ["PrivateCleanHumanly"] = Sizes.Humane(result.PrivateClean),
                        ["TotalCleanHumanly"]   = Sizes.Humane(result.SharedClean + result.PrivateClean)
                    },
                    ["Details"] = result.Json
                };

                using (var write = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    context.Write(write, djv);
                }
                return(Task.CompletedTask);
            }
        }
예제 #6
0
 public static IOMetricsRecentStats GetIoMetricsRecentStats(IoMeterBuffer.MeterItem recentMetric)
 {
     return(new IOMetricsRecentStats
     {
         Start = recentMetric.Start.GetDefaultRavenFormat(true),
         Size = recentMetric.Size,
         Acceleration = recentMetric.Acceleration,
         CompressedSize = recentMetric.CompressedSize,
         HumaneCompressedSize = Sizes.Humane(recentMetric.CompressedSize),
         HumaneSize = Sizes.Humane(recentMetric.Size),
         FileSize = recentMetric.FileSize,
         HumaneFileSize = Sizes.Humane(recentMetric.FileSize),
         Duration = Math.Round(recentMetric.Duration.TotalMilliseconds, 2),
         Type = recentMetric.Type
     });
 }
예제 #7
0
        public Task GetDocSize()
        {
            var id = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    var document = Database.DocumentsStorage.GetDocumentMetrics(context, id);
                    if (document == null)
                    {
                        HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                        return(Task.CompletedTask);
                    }
                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();

                        writer.WritePropertyName("Id");
                        writer.WriteString(id);
                        writer.WriteComma();

                        writer.WritePropertyName("ActualSize");
                        writer.WriteInteger(document.Value.ActualSize);
                        writer.WriteComma();


                        writer.WritePropertyName("HumaneActualSize");
                        writer.WriteString(Sizes.Humane(document.Value.ActualSize));
                        writer.WriteComma();


                        writer.WritePropertyName("AllocatedSize");
                        writer.WriteInteger(document.Value.AllocatedSize);
                        writer.WriteComma();

                        writer.WritePropertyName("HumaneAllocatedSize");
                        writer.WriteString(Sizes.Humane(document.Value.AllocatedSize));

                        writer.WriteEndObject();
                    }

                    return(Task.CompletedTask);
                }
        }
예제 #8
0
        private DynamicJsonValue GetFileMetrics(IoMetrics.FileIoMetrics fileMetric)
        {
            var recent  = new DynamicJsonArray();
            var history = new DynamicJsonArray();
            var djv     = new DynamicJsonValue
            {
                ["File"]    = Path.GetFileName(fileMetric.FileName),
                ["Status"]  = fileMetric.Closed ? "Closed" : "InUse",
                ["Recent"]  = recent,
                ["History"] = history
            };


            foreach (var recentMetric in fileMetric.GetRecentMetrics())
            {
                recent.Add(new DynamicJsonValue
                {
                    ["Start"]      = recentMetric.Start.GetDefaultRavenFormat(),
                    ["Size"]       = recentMetric.Size,
                    ["HumaneSize"] = Sizes.Humane(recentMetric.Size),
                    ["Duration"]   = Math.Round(recentMetric.Duration.TotalMilliseconds, 2),
                    ["Type"]       = recentMetric.Type.ToString()
                });
            }

            foreach (var historyMetric in fileMetric.GetSummaryMetrics())
            {
                history.Add(new DynamicJsonValue
                {
                    ["Start"]          = historyMetric.TotalTimeStart.GetDefaultRavenFormat(),
                    ["End"]            = historyMetric.TotalTimeEnd.GetDefaultRavenFormat(),
                    ["Size"]           = historyMetric.TotalSize,
                    ["HumaneSize"]     = Sizes.Humane(historyMetric.TotalSize),
                    ["Duration"]       = Math.Round((historyMetric.TotalTimeEnd - historyMetric.TotalTimeStart).TotalMilliseconds, 2),
                    ["ActiveDuration"] = Math.Round(historyMetric.TotalTime.TotalMilliseconds, 2),
                    ["MaxDuration"]    = Math.Round(historyMetric.MaxTime.TotalMilliseconds, 2),
                    ["MinDuration"]    = Math.Round(historyMetric.MinTime.TotalMilliseconds, 2),
                    ["Type"]           = historyMetric.Type.ToString()
                });
            }

            return(djv);
        }
예제 #9
0
        private static IOMetricsFileStats GetFileMetrics(IoMetrics.FileIoMetrics fileMetric)
        {
            var fileMetrics = new IOMetricsFileStats
            {
                File   = Path.GetFileName(fileMetric.FileName),
                Status = fileMetric.Closed ? FileStatus.Closed : FileStatus.InUse
            };

            foreach (var recentMetric in fileMetric.GetRecentMetrics())
            {
                fileMetrics.Recent.Add(GetIoMetricsRecentStats(recentMetric));
            }

            foreach (var historyMetric in fileMetric.GetSummaryMetrics())
            {
                fileMetrics.History.Add(new IOMetricsHistoryStats
                {
                    Start                = historyMetric.TotalTimeStart.GetDefaultRavenFormat(true),
                    End                  = historyMetric.TotalTimeEnd.GetDefaultRavenFormat(true),
                    Size                 = historyMetric.TotalSize,
                    HumaneSize           = Sizes.Humane(historyMetric.TotalSize),
                    FileSize             = historyMetric.TotalFileSize,
                    HumaneFileSize       = Sizes.Humane(historyMetric.TotalFileSize),
                    Duration             = Math.Round((historyMetric.TotalTimeEnd - historyMetric.TotalTimeStart).TotalMilliseconds, 2),
                    ActiveDuration       = Math.Round(historyMetric.TotalTime.TotalMilliseconds, 2),
                    MaxDuration          = Math.Round(historyMetric.MaxTime.TotalMilliseconds, 2),
                    MinDuration          = Math.Round(historyMetric.MinTime.TotalMilliseconds, 2),
                    MaxAcceleration      = historyMetric.MaxAcceleration,
                    MinAcceleration      = historyMetric.MinAcceleration,
                    CompressedSize       = historyMetric.TotalCompressedSize,
                    HumaneCompressedSize = Sizes.Humane(historyMetric.TotalCompressedSize),
                    Type                 = historyMetric.Type
                });
            }

            return(fileMetrics);
        }
예제 #10
0
        private IOMetricsResponse PrepareIOMetrics()
        {
            // 0. Prepare Response Object - Keep envs order the same as in the static endpoint response !
            var  preparedMetricsResponse = new IOMetricsResponse();
            bool responseHasContent      = false;

            // 1. Iterate over environments files in dictionary
            foreach (var envFile in _perEnvironmentsFilesMetrics)
            {
                // 2. Retrieve/Take meter items per environment file from the collection in dictionary
                var listOfMeterItems = new List <IoMeterBuffer.MeterItem>();
                while (envFile.Value.TryTake(out IoMeterBuffer.MeterItem newItem))
                {
                    listOfMeterItems.Add(newItem);
                }

                if (listOfMeterItems.Count == 0)
                {
                    continue;
                }

                // 3. Get env path & file name from dictionary item
                var meterItem = listOfMeterItems[0];
                var file      = new FileInfo(envFile.Key);
                var envPath   = file.Directory;
                if (meterItem.Type == IoMetrics.MeterType.Compression || meterItem.Type == IoMetrics.MeterType.JournalWrite)
                {
                    envPath = envPath?.Parent;
                }

                // 3a. Should not happen, but being extra careful here
                if (envPath == null)
                {
                    continue;
                }

                // 4. Find relevant environment
                var currentEnvironment = preparedMetricsResponse.Environments.FirstOrDefault(x => x.Path == envPath.FullName);
                if (currentEnvironment == null)
                {
                    // If new index for example was added...
                    currentEnvironment = new IOMetricsEnvironment {
                        Path = envPath.FullName, Files = new List <IOMetricsFileStats>()
                    };
                    preparedMetricsResponse.Environments.Add(currentEnvironment);
                }

                if (currentEnvironment.Path == _basePath)
                {
                    currentEnvironment.Path = Path.Combine(_basePath, "Documents");
                }

                // 5. Prepare response, add recent items.  Note: History items are not added since studio does not display them anyway
                var preparedFilesInfo = currentEnvironment.Files.FirstOrDefault(x => x.File == file.Name) ?? new IOMetricsFileStats
                {
                    File = file.Name
                };

                currentEnvironment.Files.Add(preparedFilesInfo);

                foreach (var item in listOfMeterItems)
                {
                    var preparedRecentStats = new IOMetricsRecentStats
                    {
                        Start          = item.Start.GetDefaultRavenFormat(),
                        Size           = item.Size,
                        HumaneSize     = Sizes.Humane(item.Size),
                        FileSize       = item.FileSize,
                        HumaneFileSize = Sizes.Humane(item.FileSize),
                        Duration       = Math.Round(item.Duration.TotalMilliseconds, 2),
                        Type           = item.Type
                    };

                    responseHasContent = true;
                    preparedFilesInfo.Recent.Add(preparedRecentStats);
                }
            }

            if (responseHasContent == false)
            {
                return(null);
            }

            return(preparedMetricsResponse);
        }
예제 #11
0
 public static void SetMinimalHumaneMeterData(this MeterMetric self, string name, DynamicJsonValue obj)
 {
     obj["HumaneTotal" + name]     = Sizes.Humane(self.Count);
     obj["Humane" + name + "Rate"] = Sizes.Humane((long)self.OneMinuteRate);
 }
예제 #12
0
        public static void SetFileLength(SafeFileHandle fileHandle, long length)
        {
            if (SetFilePointerEx(fileHandle, length, IntPtr.Zero, Win32NativeFileMoveMethod.Begin) == false)
            {
                var filePath  = GetFilePath();
                var exception = new Win32Exception(Marshal.GetLastWin32Error());
                throw new IOException($"Could not move the pointer of file {filePath}", exception);
            }

            if (SetEndOfFile(fileHandle) == false)
            {
                var filePath  = GetFilePath();
                var lastError = Marshal.GetLastWin32Error();
                if (lastError == (int)Win32NativeFileErrors.ERROR_DISK_FULL)
                {
                    var driveInfo = DiskSpaceChecker.GetDiskSpaceInfo(filePath);
                    throw new DiskFullException(filePath, length, driveInfo?.TotalFreeSpace.GetValue(SizeUnit.Bytes));
                }

                var exception = new Win32Exception(lastError);

                if (lastError == (int)Win32NativeFileErrors.ERROR_NOT_READY ||
                    lastError == (int)Win32NativeFileErrors.ERROR_FILE_NOT_FOUND)
                {
                    throw new IOException($"Could not set the size of file {filePath} because it is inaccessible.", exception);
                }

                throw new IOException($"Could not set the size of file {filePath} to {Sizes.Humane(length)}", exception);
            }

            string GetFilePath()
            {
                try
                {
                    return(DiskSpaceChecker.GetWindowsRealPathByHandle(fileHandle.DangerousGetHandle()));
                }
                catch
                {
                    return(null);
                }
            }
        }
예제 #13
0
        public static void SetFileLength(SafeFileHandle fileHandle, long length, string filePath)
        {
            if (SetFilePointerEx(fileHandle, length, IntPtr.Zero, Win32NativeFileMoveMethod.Begin) == false)
            {
                var exception = new Win32Exception(Marshal.GetLastWin32Error());
                throw new IOException($"Could not move the pointer of file {filePath}", exception);
            }

            if (SetEndOfFile(fileHandle) == false)
            {
                var lastError = Marshal.GetLastWin32Error();
                if (lastError == (int)Win32NativeFileErrors.ERROR_DISK_FULL)
                {
                    var directoryPath = Path.GetDirectoryName(filePath);
                    // disk space info is expecting the directory path and not the file path
                    var driveInfo = DiskSpaceChecker.GetDiskSpaceInfo(directoryPath);
                    throw new DiskFullException(filePath, length, driveInfo?.TotalFreeSpace.GetValue(SizeUnit.Bytes), new Win32Exception(lastError).Message);
                }

                var exception = new Win32Exception(lastError);

                if (lastError == (int)Win32NativeFileErrors.ERROR_NOT_READY ||
                    lastError == (int)Win32NativeFileErrors.ERROR_FILE_NOT_FOUND)
                {
                    throw new IOException($"Could not set the size of file {filePath} because it is inaccessible.", exception);
                }

                throw new IOException($"Could not set the size of file {filePath} to {Sizes.Humane(length)}", exception);
            }
        }
예제 #14
0
        public static (long WorkingSet, long ProcessClean, DynamicJsonArray Json) GetMaps()
        {
            long processClean = 0;

            const uint uintMaxVal = uint.MaxValue;
            var        dja        = new DynamicJsonArray();

            GetSystemInfo(out var systemInfo);

            var procMinAddress = systemInfo.minimumApplicationAddress;
            var procMaxAddress = systemInfo.maximumApplicationAddress;
            var processHandle  = GetCurrentProcess();
            var results        = new Dictionary <string, Tuple <long, long> >();

            while (procMinAddress.ToInt64() < procMaxAddress.ToInt64())
            {
                MEMORY_BASIC_INFORMATION memoryBasicInformation;
                VirtualQueryEx(processHandle, (byte *)procMinAddress.ToPointer(),
                               &memoryBasicInformation, new UIntPtr((uint)sizeof(MEMORY_BASIC_INFORMATION)));

                // if this memory chunk is accessible
                if (memoryBasicInformation.Protect == (uint)MemoryProtectionConstants.PAGE_READWRITE &&
                    memoryBasicInformation.State == (uint)MemoryStateConstants.MEM_COMMIT &&
                    memoryBasicInformation.Type == (uint)MemoryTypeConstants.MEM_MAPPED)
                {
                    var encodedString = GetEncodedFilename(processHandle, ref memoryBasicInformation);
                    if (encodedString != null)
                    {
                        var regionSize = memoryBasicInformation.RegionSize.ToInt64();
                        for (long size = uintMaxVal; size < regionSize + uintMaxVal; size += uintMaxVal)
                        {
                            var partLength = size > regionSize ? regionSize % uintMaxVal : uintMaxVal;

                            var totalDirty = AddressWillCauseHardPageFault((byte *)memoryBasicInformation.BaseAddress.ToPointer(), (uint)partLength,
                                                                           performCount: true);
                            var totalClean = partLength - totalDirty;

                            if (results.TryGetValue(encodedString, out var values))
                            {
                                var prevValClean = values.Item1 + totalClean;
                                var prevValDirty = values.Item2 + totalDirty;
                                results[encodedString] = new Tuple <long, long>(prevValClean, prevValDirty);
                            }
                            else
                            {
                                results[encodedString] = new Tuple <long, long>(totalClean, totalDirty);
                            }

                            processClean += totalClean;
                        }
                    }
                }

                // move to the next memory chunk
                procMinAddress = new IntPtr(procMinAddress.ToInt64() + memoryBasicInformation.RegionSize.ToInt64());
            }



            foreach (var result in results)
            {
                var clean = result.Value.Item1;
                var dirty = result.Value.Item2;

                var djv = new DynamicJsonValue
                {
                    ["File"]              = result.Key,
                    ["Size"]              = "N/A",
                    ["Rss"]               = "N/A",
                    ["SharedClean"]       = "N/A",
                    ["SharedDirty"]       = "N/A",
                    ["PrivateClean"]      = "N/A",
                    ["PrivateDirty"]      = "N/A",
                    ["TotalClean"]        = clean,
                    ["TotalCleanHumanly"] = Sizes.Humane(clean),
                    ["TotalDirty"]        = dirty,
                    ["TotalDirtyHumanly"] = Sizes.Humane(dirty)
                };

                dja.Add(djv);
            }

            using (var currentProcess = Process.GetCurrentProcess())
            {
                var workingSet = currentProcess.WorkingSet64;
                return(workingSet, processClean, dja);
            }
        }
예제 #15
0
        public (long Rss, long SharedClean, long PrivateClean, DynamicJsonArray Json) CalculateMemUsageFromSmaps()
        {
            var state = SearchState.None;
            var dja   = new DynamicJsonArray();

            using (var currentProcess = Process.GetCurrentProcess())
                using (var fileStream = new FileStream($"/proc/{currentProcess.Id}/smaps", FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    var    read = ReadFromFile(fileStream, _currentBuffer);
                    var    offsetForNextBuffer = 0;
                    long   tmpRss = 0, tmpSharedClean = 0, tmpPrivateClean = 0;
                    string resultString = null;
                    long   valSize = 0, valRss = 0, valPrivateDirty = 0, valSharedDirty = 0, valSharedClean = 0, valPrivateClean = 0;
                    while (true)
                    {
                        if (read == 0)
                        {
                            return(tmpRss, tmpSharedClean, tmpPrivateClean, dja);
                        }

                        var switchBuffer = false;
                        for (var i = offsetForNextBuffer; i < _endOfBuffer[_currentBuffer]; i++)
                        {
                            byte[] term;
                            var    offset = 0;
                            if (_smapsBuffer[_currentBuffer][i] == 'r')
                            {
                                term = _rwsBytes;
                            }
                            else if (_smapsBuffer[_currentBuffer][i] == 'R')
                            {
                                term = _rssBytes;
                            }
                            else if (_smapsBuffer[_currentBuffer][i] == 'S')
                            {
                                term   = _sizeBytes; // or SharedDirty or SharedCleanBytes (which ARE longer in length from Size)
                                offset = _sharedCleanBytes.Length - term.Length;
                            }
                            else if (_smapsBuffer[_currentBuffer][i] == 'P')
                            {
                                term = _privateCleanBytes; // or PrivateDirty (which is not longer in length from PrivateCleanBytes)
                            }
                            else if (_smapsBuffer[_currentBuffer][i] == 'L')
                            {
                                term = _lockedBytes;
                            }
                            else
                            {
                                continue;
                            }

                            // check if the current buffer too small for the search term and read next buff if so
                            if (switchBuffer == false && i + term.Length + offset > _endOfBuffer[_currentBuffer])
                            {
                                var nextBuffer = (_currentBuffer + 1) % 2;
                                read         = ReadFromFile(fileStream, nextBuffer);
                                switchBuffer = true;
                            }

                            var searchedBuffer   = _currentBuffer;
                            var positionToSearch = i;
                            var hasMatch         = true;
                            for (var j = 1; j < term.Length; j++)
                            {
                                positionToSearch++;
                                if (positionToSearch == _smapsBuffer[searchedBuffer].Length)
                                {
                                    // we assume max search term length doesn't exceed buffer length..
                                    searchedBuffer   = (searchedBuffer + 1) % 2;
                                    positionToSearch = 0;
                                    Debug.Assert(switchBuffer);
                                }

                                // for 'S' and 'P' we might have to search different term:
                                if (_smapsBuffer[searchedBuffer][positionToSearch] != term[j])
                                {
                                    if (term == _privateCleanBytes) // didn't find PrivateCleanBytes - try to find PrivateDiryBytes
                                    {
                                        term = _privateDirtyBytes;
                                        if (_smapsBuffer[searchedBuffer][positionToSearch] == term[j])
                                        {
                                            continue;
                                        }
                                    }

                                    if (term == _sizeBytes) // didn't find Size - try to find SharedCleanBytes
                                    {
                                        term = _sharedCleanBytes;
                                        if (_smapsBuffer[searchedBuffer][positionToSearch] == term[j])
                                        {
                                            continue;
                                        }
                                    }

                                    if (term == _sharedCleanBytes) // didn't find SharedCleanBytes - try to find SharedDirtyBytes
                                    {
                                        term = _sharedDirtyBytes;
                                        if (_smapsBuffer[searchedBuffer][positionToSearch] == term[j])
                                        {
                                            continue;
                                        }
                                    }

                                    hasMatch = false;
                                    break;
                                }
                            }

                            if (hasMatch == false)
                            {
                                continue;
                            }

                            // now read value.. search until reached letter 'B' (value ends with "kB")
                            var bytesSearched       = 0;
                            var posInTempBuf        = 0;
                            var valueSearchPosition = i + term.Length;
                            var foundValue          = false;
                            var foundK = false;

                            while (bytesSearched < _tempBufferBytes.Length) // just a bullpark figure, usually ~40 bytes are enough
                            {
                                if (valueSearchPosition == _smapsBuffer[searchedBuffer].Length)
                                {
                                    searchedBuffer      = (_currentBuffer + 1) % 2;
                                    valueSearchPosition = 0;

                                    if (switchBuffer == false)
                                    {
                                        var readFromNextBuffer = ReadFromFile(fileStream, searchedBuffer);
                                        if (readFromNextBuffer == 0)
                                        {
                                            // this should not happen, the file ended without a value
                                            break;
                                        }

                                        switchBuffer = true;
                                    }
                                }

                                var currentChar = _smapsBuffer[searchedBuffer][valueSearchPosition];

                                if (term == _rwsBytes) // value is filename which comes after last white-space and before '\n'
                                {
                                    // zero previous entries
                                    if (posInTempBuf == 0)
                                    {
                                        resultString    = null; // zero previous entries
                                        valSize         = 0;
                                        valRss          = 0;
                                        valPrivateDirty = 0;
                                        valSharedDirty  = 0;
                                        valSharedClean  = 0;
                                        valPrivateClean = 0;
                                    }

                                    if (currentChar == ' ' || currentChar == '\t')
                                    {
                                        posInTempBuf = 0;
                                    }
                                    else if (currentChar == '\n')
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        _tempBufferBytes[posInTempBuf++] = currentChar;
                                    }
                                }
                                else
                                {
                                    if (currentChar >= '0' && currentChar <= '9')
                                    {
                                        _tempBufferBytes[posInTempBuf++] = currentChar;
                                    }

                                    if (currentChar == 'k')
                                    {
                                        foundK = true;
                                    }

                                    if (currentChar == 'B')
                                    {
                                        foundValue = true;
                                        break;
                                    }
                                }

                                ++valueSearchPosition;
                                ++bytesSearched;
                            }

                            if (term != _rwsBytes)
                            {
                                if (foundValue == false)
                                {
                                    ThrowNotContainsValidValue(term, currentProcess.Id);
                                }
                                if (foundK == false)
                                {
                                    ThrowNotContainsKbValue(term, currentProcess.Id);
                                }
                            }


                            i += term.Length + bytesSearched;
                            if (i >= _smapsBuffer[_currentBuffer].Length)
                            {
                                offsetForNextBuffer = _smapsBuffer[_currentBuffer].Length - i;
                            }
                            else
                            {
                                offsetForNextBuffer = 0;
                            }


                            long resultLong = 0;
                            if (term != _rwsBytes)
                            {
                                var multiplier = 1;
                                for (var j = posInTempBuf - 1; j >= 0; j--)
                                {
                                    resultLong += (_tempBufferBytes[j] - (byte)'0') * multiplier;
                                    multiplier *= 10;
                                }

                                resultLong *= 1024; // "kB"
                            }
                            else
                            {
                                resultString = posInTempBuf > 0 ? Encoding.UTF8.GetString(_tempBufferBytes, 0, posInTempBuf) : "";
                            }

                            if (term == _rwsBytes)
                            {
                                if (state != SearchState.None)
                                {
                                    ThrowNotRwsTermAfterLockedTerm(state, term, currentProcess.Id);
                                }
                                state = SearchState.Rws;
                            }
                            else if (term == _sizeBytes)
                            {
                                if (state != SearchState.Rws)
                                {
                                    continue; // found Rss but not after rw-s - irrelevant
                                }
                                state   = SearchState.Size;
                                valSize = resultLong;
                            }
                            else if (term == _rssBytes)
                            {
                                if (state != SearchState.Size)
                                {
                                    continue; // found Rss but not after rw-s - irrelevant
                                }
                                state   = SearchState.Rss;
                                tmpRss += resultLong;
                                valRss  = resultLong;
                            }
                            else if (term == _sharedCleanBytes)
                            {
                                if (state != SearchState.Rss)
                                {
                                    continue; // found Shared_Clean but not after Rss (which must come after rw-s) - irrelevant
                                }
                                state           = SearchState.SharedClean;
                                tmpSharedClean += resultLong;
                                valSharedClean  = resultLong;
                            }
                            else if (term == _sharedDirtyBytes)
                            {
                                if (state != SearchState.SharedClean)
                                {
                                    continue;
                                }
                                state          = SearchState.SharedDirty;
                                valSharedDirty = resultLong;
                            }
                            else if (term == _privateCleanBytes)
                            {
                                if (state != SearchState.SharedDirty)
                                {
                                    continue;
                                }
                                state            = SearchState.PrivateClean;
                                tmpPrivateClean += resultLong;
                                valPrivateClean  = resultLong;
                            }
                            else if (term == _privateDirtyBytes)
                            {
                                if (state != SearchState.PrivateClean)
                                {
                                    continue;
                                }
                                state           = SearchState.PrivateDirty;
                                valPrivateDirty = resultLong;
                            }
                            else if (term == _lockedBytes)
                            {
                                if (state != SearchState.PrivateDirty)
                                {
                                    continue;
                                }
                                state = SearchState.None;

                                if (resultString == null)
                                {
                                    ThrowOnNullString();
                                }

                                if (resultString.EndsWith(".voron") == false &&
                                    resultString.EndsWith(".buffers") == false)
                                {
                                    continue;
                                }

                                var djv = new DynamicJsonValue
                                {
                                    ["File"]              = resultString,
                                    ["Size"]              = Sizes.Humane(valSize),
                                    ["Rss"]               = Sizes.Humane(valRss),
                                    ["SharedClean"]       = Sizes.Humane(valSharedClean),
                                    ["SharedDirty"]       = Sizes.Humane(valSharedDirty),
                                    ["PrivateClean"]      = Sizes.Humane(valPrivateClean),
                                    ["PrivateDirty"]      = Sizes.Humane(valPrivateDirty),
                                    ["TotalClean"]        = valSharedClean + valPrivateClean,
                                    ["TotalCleanHumanly"] = Sizes.Humane(valSharedClean + valPrivateClean),
                                    ["TotalDirty"]        = valSharedDirty + valPrivateDirty,
                                    ["TotalDirtyHumanly"] = Sizes.Humane(valSharedDirty + valPrivateDirty)
                                };
                                dja.Add(djv);
                            }
                            else
                            {
                                throw new InvalidOperationException($"Reached unknown unhandled term: '{Encoding.UTF8.GetString(term)}'");
                            }
                        }


                        _currentBuffer = (_currentBuffer + 1) % 2;
                        if (switchBuffer == false)
                        {
                            read = ReadFromFile(fileStream, _currentBuffer);
                            if (read == 0)
                            {
                                break;
                            }
                        }
                    }

                    return(tmpRss, tmpSharedClean, tmpPrivateClean, dja);
                }
        }
예제 #16
0
        public Task MemorySmaps()
        {
            if (PlatformDetails.RunningOnLinux == false)
            {
                using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
                    using (var process = Process.GetCurrentProcess())
                    {
                        var sharedClean = MemoryInformation.GetSharedCleanInBytes(process);
                        var rc          = Win32MemoryQueryMethods.GetMaps();
                        var djv         = new DynamicJsonValue
                        {
                            ["Totals"] = new DynamicJsonValue
                            {
                                ["WorkingSet"]          = process.WorkingSet64,
                                ["SharedClean"]         = Sizes.Humane(sharedClean),
                                ["PrivateClean"]        = "N/A",
                                ["TotalClean"]          = rc.ProcessClean,
                                ["RssHumanly"]          = Sizes.Humane(process.WorkingSet64),
                                ["SharedCleanHumanly"]  = Sizes.Humane(sharedClean),
                                ["PrivateCleanHumanly"] = "N/A",
                                ["TotalCleanHumanly"]   = Sizes.Humane(rc.ProcessClean)
                            },
                            ["Details"] = rc.Json
                        };
                        using (var write = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                        {
                            context.Write(write, djv);
                        }
                        return(Task.CompletedTask);
                    }
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
            {
                var buffers = new[]
                {
                    ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize),
                    ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize)
                };
                try
                {
                    var result     = new SmapsReader(buffers).CalculateMemUsageFromSmaps <SmapsReaderJsonResults>();
                    var procStatus = MemoryInformation.GetMemoryUsageFromProcStatus();
                    var djv        = new DynamicJsonValue
                    {
                        ["Totals"] = new DynamicJsonValue
                        {
                            ["WorkingSet"]            = result.Rss,
                            ["SharedClean"]           = result.SharedClean,
                            ["PrivateClean"]          = result.PrivateClean,
                            ["TotalClean"]            = result.SharedClean + result.PrivateClean,
                            ["TotalDirty"]            = result.TotalDirty, // This includes not only r-ws buffer and voron files, but also dotnet's and heap dirty memory
                            ["WorkingSetSwap"]        = result.Swap,       // Swap values sum for r-ws entries only
                            ["Swap"]                  = procStatus.Swap,
                            ["RssHumanly"]            = Sizes.Humane(result.Rss),
                            ["SwapHumanly"]           = Sizes.Humane(procStatus.Swap),
                            ["WorkingSetSwapHumanly"] = Sizes.Humane(result.Swap),
                            ["SharedCleanHumanly"]    = Sizes.Humane(result.SharedClean),
                            ["PrivateCleanHumanly"]   = Sizes.Humane(result.PrivateClean),
                            ["TotalCleanHumanly"]     = Sizes.Humane(result.SharedClean + result.PrivateClean)
                        },
                        ["Details"] = result.SmapsResults.ReturnResults()
                    };

                    using (var write = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        context.Write(write, djv);
                    }

                    return(Task.CompletedTask);
                }
                finally
                {
                    ArrayPool <byte> .Shared.Return(buffers[0]);

                    ArrayPool <byte> .Shared.Return(buffers[1]);
                }
            }
        }
예제 #17
0
 public override string ToString()
 {
     return($"Allocated {Sizes.Humane(Allocated)}, Used {Sizes.Humane(_used)}");
 }
예제 #18
0
        public static void SetFileLength(SafeFileHandle fileHandle, long length)
        {
            if (SetFilePointerEx(fileHandle, length, IntPtr.Zero, Win32NativeFileMoveMethod.Begin) == false)
            {
                var exception = new Win32Exception(Marshal.GetLastWin32Error());

                var filePath = GetFilePath();

                throw new IOException($"Could not move the pointer of file {filePath}", exception);
            }

            if (SetEndOfFile(fileHandle) == false)
            {
                var lastError = Marshal.GetLastWin32Error();

                var filePath = GetFilePath();

                if (lastError == (int)Win32NativeFileErrors.ERROR_DISK_FULL)
                {
                    long?freeSpaceAvailable = null;

                    if (GetDiskFreeSpaceEx(Path.GetDirectoryName(filePath),
                                           out _,
                                           out _,
                                           out var totalFreeAvailable))
                    {
                        freeSpaceAvailable = (long)totalFreeAvailable;
                    }

                    throw new DiskFullException(filePath, length, freeSpaceAvailable);
                }

                var exception = new Win32Exception(lastError);

                if (lastError == (int)Win32NativeFileErrors.ERROR_NOT_READY ||
                    lastError == (int)Win32NativeFileErrors.ERROR_FILE_NOT_FOUND)
                {
                    throw new IOException($"Could not set the size of file {filePath} because it is inaccessible.", exception);
                }

                throw new IOException($"Could not set the size of file {filePath} to {Sizes.Humane(length)}", exception);
            }

            string GetFilePath()
            {
                var filePath = new StringBuilder(256);

                while (GetFinalPathNameByHandle(fileHandle, filePath, filePath.Capacity, 0) > filePath.Capacity &&
                       filePath.Capacity < 32767) // max unicode path length
                {
                    filePath.EnsureCapacity(filePath.Capacity * 2);
                }

                return(filePath.ToString());
            }
        }