Eventstore: EsDriveInfo is broken for Unix with ZFS

Created on 4 Jan 2018  路  1Comment  路  Source: EventStore/EventStore

The Mono implementation of DriveInfo you use is broken with regards to using ZFS. I keep getting spammed in the ES log by this:

Error while reading drive info for path /data/es. Message: The drive name does not exist
Parameter name: driveName.

Because somehow DriveInfo is not able to handle the case when using ZFS datasets that are mounted.

Here is the fix:

using System;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using EventStore.Common.Log;
using EventStore.Common.Utils;
using EventStore.Core.Services.Monitoring.Utils;

namespace EventStore.Core.Services.Monitoring.Stats
{
    public class EsDriveInfo
    {
        public readonly string DiskName;
        public readonly long TotalBytes;
        public readonly long AvailableBytes;
        public readonly long UsedBytes;
        public readonly string Usage;

        public static EsDriveInfo FromDirectory(string path)
        {
            try
            {
                if (IsUnix) return GetEsDriveInfoUnix(path);

                var drive = new DriveInfo(Directory.GetDirectoryRoot(path));
                return new EsDriveInfo(drive.Name, drive.TotalSize, drive.AvailableFreeSpace);
            }
            catch (Exception ex)
            {
                Console.Error.Write("Error while reading drive info for path {0}. Message: {1}.", path, ex.Message);
                return null;
            }
        }

        private EsDriveInfo(string diskName, long totalBytes, long availableBytes)
        {
            DiskName = diskName;
            TotalBytes = totalBytes;
            AvailableBytes = availableBytes;
            UsedBytes = TotalBytes - AvailableBytes;
            Usage = TotalBytes != 0
                    ? (UsedBytes * 100 / TotalBytes).ToString(CultureInfo.InvariantCulture) + "%"
                    : "0%";
        }

        private static EsDriveInfo GetEsDriveInfoUnix(string directory)
        {


            // http://unix.stackexchange.com/questions/11311/how-do-i-find-on-which-physical-device-a-folder-is-located

            // example

            // Filesystem     1K-blocks      Used Available Use% Mounted on
            // /dev/sda1      153599996 118777100  34822896  78% /media/CC88FD3288FD1C20

            try
            {
                if(!Directory.Exists(directory)) return null;
                var driveInfo = ShellExecutor.GetOutput("df", $"-P {directory}");
                var driveInfoLines = driveInfo.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                if(driveInfoLines.Length == 0) return null;
                var ourline = driveInfoLines[1];
                var trimmedLine = SpacesRegex.Replace(ourline, " ");
                var info = trimmedLine.Split(' ');

                var totalBytes     = long.Parse(info[1].Trim()); // the '1024-blocks' column
                var availableBytes = long.Parse(info[3].Trim()); // the 'Available' column
                var mountPoint     = info[5];                    // the 'Mounted on' column

                return new EsDriveInfo(mountPoint, totalBytes, availableBytes);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine("Could not get drive name for directory '{0}' on Unix - {1}", directory, ex.Message);
                return null;
            }
        }
}
kinbug

Most helpful comment

Thanks @ahjohannessen, we'll work on integrating a fix for this since ZFS is a recommended configuration. This fix looks great given the infrequency with which it is executed - we'll likely look at PInvoking libzfs functions directly if it becomes a bottleneck.

>All comments

Thanks @ahjohannessen, we'll work on integrating a fix for this since ZFS is a recommended configuration. This fix looks great given the infrequency with which it is executed - we'll likely look at PInvoking libzfs functions directly if it becomes a bottleneck.

Was this page helpful?
0 / 5 - 0 ratings