1

Please note that I am running a Windows Service application using the .NET Framework 4.6.2, and only occasionally it gets this error:

2019-04-22 18:35:36.7727|ERROR|DataIntegrator.MyService|ERROR: code = IoErr (10), message = System.Data.SQLite.SQLiteException (0x800007FF): disk I/O error
disk I/O error
   at System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQLiteStatement previous, UInt32 timeoutMS, String& strRemain)
   at System.Data.SQLite.SQLiteCommand.BuildNextCommand()
   at System.Data.SQLite.SQLiteDataReader.NextResult()
   at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
   at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(CommandBehavior behavior)
   at System.Data.SQLite.SQLiteHelper.Insert(String tableName, Dictionary`2 dic) in C:\Projects\DataIntegrator\DataIntegrator\DataAccessLayer\SQLiteHelper.cs:line 254
   at System.Data.SQLite.Insert.InsertTag(Tag tag) in C:\Projects\DataIntegrator\DataIntegrator\DataAccessLayer\Query\Insert.cs:line 60

Here is my code with the error happening on the sh.Insert line:

    public static void InsertTag(Tag tag)
    {
        try
        {
            using (SQLiteConnection conn = new SQLiteConnection(Constants.DataSource))
            {
                using (SQLiteCommand cmd = new SQLiteCommand())
                {
                    cmd.Connection = conn;
                    conn.Open();

                    SQLiteHelper sh = new SQLiteHelper(cmd);

                    var dic = new Dictionary<string, object>();
                    dic["Id"] = tag.Id;
                    dic["Item"] = tag.Item;
                    dic["Value"] = tag.Value;
                    dic["Source"] = tag.Source;

                    sh.Insert(Constants.TagTable, dic);

                    conn.Close();
                }
            }
        }
        catch (Exception ex)
        {
            LogError("ERROR: {0}", ex.ToString());
        }
    }

Does anyone have any suggestions? Here are some other links I have checked but haven't found a solution yet:

SQLiteDiskIOException with error code 10: disk I/O error

sqlite3 disk I/O error on cli

https://dba.stackexchange.com/questions/93575/sqlite-disk-i-o-error-3850

https://github.com/linuxserver/docker-sonarr/issues/38

https://forums.sonarr.tv/t/disk-i-o-and-sqllite-error/5578

In the last one it mentions that the database is corrupt but when I stop the console app I can open the database. Should I be using a different database like Berkeley DB that potentially has better performance?

https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html

http://www.tsjensen.com/blog/post/2011/09/03/How+To+Get+Berkeley+DB+5228+And+NET+Examples+Working+In+Visual+Studio+2010+SP1

UPDATE:

Added OS to tags

user8128167
  • 6,929
  • 6
  • 66
  • 79
  • The error seems to happen `SQLiteHelper.cs:line 254`, not in `InsertTag`. `InsertTag` (`Insert.cs:line 60`) is where `SQLiteHelper` is called. – Olivier Jacot-Descombes Apr 23 '19 at 14:04
  • SQLite is not a database server that is designed to handle large files. SQLite simply reads from the file on your PC. I would recommend using SQL Server (or Express) which you can download from msdn for free and will give much better performance that SQLite. – jdweng Apr 23 '19 at 14:05
  • Thanks for the suggestion--I just added the OS. Please note that I am using a resource restricted device so adding a full database server like SQL Server is not an option. Also, the files that I am dealing with are not overly large--like maybe 100 MB of data over the course of a couple days. – user8128167 Apr 23 '19 at 14:14
  • 1
    Running through a Windows service; if you are also running the database file from a network share, remember that SQLite requires robust file-locking from the OS, and there have been problems in the past with Windows network file-locking not quite cutting the mustard. – Mark Benningfield Apr 23 '19 at 16:39
  • @user8128167, could I confirm with you that the Windows Service in your post means a .net core app hosted as a windows service? Or it is a background app? – Michael Xu Apr 24 '19 at 07:55
  • It is a .NET Framework 4.6.2 hosted as a Windows Service. – user8128167 Apr 24 '19 at 18:25
  • 1
    @user8128167, as far as i know, Windows IoT Core can not run Windows Service developed in C#. Could you please tell me how to host the windows service on Windows IoT Core? – Michael Xu Apr 25 '19 at 02:30
  • Sorry, it actually has Windows IoT Enterprise, not Core. – user8128167 Apr 25 '19 at 15:30
  • @user8128167, as Mark Benningfield mentioned, did you run the database file from a network share? – Michael Xu Apr 26 '19 at 01:25
  • No, it is on the C:\ drive – user8128167 Apr 26 '19 at 15:50

1 Answers1

1

Please note that I originally used the synchronous DataReceived event handler, which caused the CPU to be used a lot and gave me the disk I/O errors:

    private readonly SerialPort _port = null;

    public MySerialPort(string comPortName)
    {
        ComPortName = comPortName;
        _port = new SerialPort(ComPortName,
            9600, Parity.None, 8, StopBits.One);
            _port.DataReceived -= new
                SerialDataReceivedEventHandler(port_DataReceived);
        _port.Open();
    }

    private void port_DataReceived(object sender,
        SerialDataReceivedEventArgs e)
    {
        SerialPort port = (SerialPort)sender;
        if (!port.IsOpen) return;

        for (int i = 0; i < port.BytesToRead; i++)
        {
            // process bytes
        }
    }

In order to improve performance and resolve the I/O disk error I changed to use an async event handler via the Base class:

    private readonly SerialPort _port = null;

    public MySerialPort(string comPortName)
    {
        ComPortName = comPortName;
        _port = new SerialPort(ComPortName,
            9600, Parity.None, 8, StopBits.One);
         _port.Open();
         var rxData = Task.Run(async () => await ReceiveData());
        // ...
    }


public async Task<Stream> ReceiveData()
{
    var buffer = new byte[4096];
    int readBytes = 0;
    using (MemoryStream memoryStream = new MemoryStream())
    {
        while ((readBytes = await _port.BaseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            memoryStream.Write(buffer, 0, readBytes);
        }

        return memoryStream;
    }

}

For details, please see

http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport

and

Correct Implementation of Async SerialPort Read

user8128167
  • 6,929
  • 6
  • 66
  • 79