Storagenode: allow configuring database path independently (v1.4.2 and above only)

Ok thanks ! No worry, I just wanted to figure how it works, because I’ve actually a nice unused Samsung 850 Pro on my system (since it was my old system drive), and I check the SMART and Samsung Magician for the wearing, it’s a pretty solid SSD so far, still probably for years, because I don’t think the dbs writing should be so intense compared to my previous workload usage. But, in the past, when I mapped the dbs files directly, obviously, the others db-wal were still created after the run in the default path, then there were changes with the db structures (splitting db and so on), but the node was notably faster for the orders sending and the first run. Still, it’s still works nicely on the hard drives except the database temporarly locked when the node starts/restarts, but I know its a normal behavior when it loads back the data the first time, so yes, I could just continue like that. But I wanted be sure to use that feature properly if ever I use it.

I don’t want be your ennemy because of this mistake, I appreciate you into the community Bright. I fixed myself the procedure I took for example earlier to avoid confusions for other SNOs. If we meet, I could manually press an espresso for you, since I know you’re drinking coffee the morning. Cheers! <3

No worries, you won’t make an enemy out of me. I just want you to be fully informed about the risks. The fact is the network can deal with the loss of your node should the worst happen. But I’d rather prevent that for your sake. You seem to be doing your homework though, so you’re the only one who can determine whether you feel secure enough to make this move. I’d make damn sure I actually need it though. The only reason I’m using it is because I have a device I’m certain wouldn’t be able to keep up with the db’s on the same location. It still might not even with the db’s elsewhere. But then I’m not risking my main node. Just testing out a secondary node on this device to see if it can survive.

I’d take you up on that espresso though should we ever meet! And I’ll buy a round of beers later in the day. :wink:

For me on Debian 10 works this:

  • docker stop ‘containersname’ && docker rm ‘containersname’
  • cp /‘current-path-db’/*.db /‘new-path-db’/*.db
  • add to config.yaml: storage2.database-dir: "/app/db"
  • add to docker start options: –mount type=bind,source="/‘new-path-db’",target=/app/db \

I finally got some new SSDs mirrored in the NAS. Did this on ubuntu. Your CP command wouldn’t work quite right for me.

sudo docker stop -t 300 storagenode
sudo docker rm storagenode
sudo su
CD /mnt/iscsi/StorjV3/storage
cp *.db /mnt/iscsiSSD/StorjDB
exit

add to config.yaml: storage2.database-dir: “/app/db”
add to docker start options:
–mount type=bind,source="/mnt/iscsiSSD/StorjDB",target=/app/db
Remove DB files from OLD path!

Of course, some commands need to be entered under root. It’s obvious.

This was my main point for yours VS ubuntu. the other commands are there for others convenience. Thanks for the assist!

U copy files from dir in witch u are. But input path works too. Strange why it not work for u.
Maybe u did it literally. But need cp /current-path-db/*.db /new-path-db/ without masked files at output path.

I agree. Didn’t dig too much before switching. It said the source path didn’t exist /current-path-db/*.db . I think it doesn’t like *.db being so close to the source path. Maybe it needed a space, but i backed out and did something i was more familiar with since these files are so sensitive.

I just came here to say that this still works as of v1.69.2

I am not running it under a Docker instance but rather as a Windows service.

I did have an issue where the Storage Node service wouldn’t start if my DB path was in a root directory in the root of C: but id did work if it was two directories deep from C:

i.e.
C:\StorjDB → did not work
C:\Storj\db → did work

Perhaps the issue is related to permissions, especially if you specified path as C:\, i.e. databases should be placed in the root - there are special system folders and they are not available for the service, resulting permissions denied issue and inability to access files in the root.
It’s always recommended to create a folder for data (or databases in this case) instead of using the root of the disk.

Hello,
I just manage to move the DBs to the fastest storage I have. My expectation was to reduce the I/O of my USB attached STORJ disk. That’s not happened for now. The 14 TB disk is still on the heavy load. Did I miss somth?

Moving DBs to another disk will not reduce I/O on the HDD, this only helps DBs themself to have less locks.
To reduce I/O on the HDD you need to add RAM or SSD as a caching layer, if your filesystem/OS allows to do so.
I guess it’s Windows and also in the VM?

My system is on Orangepi ARM running on 2 GB of RAM ARMBIAN linux.
I can attach a fast SSD to it as a caching layer, but I didn’t find an instruction hot to do that. Can you please guide me with that?
Thank you

With hashstore database location is not important anymore. So if migration is not already done I would recommend doing this first.

If you are doing something like mounted NFS storage – which you should not do and storj says it’s not supported and it’s a bad idea – then file locking can be a problem with the database and running the database in a separate location helps.

As @alpharabbit say - the best approach would be to migrate to hashstore, it will effectively reduce I/O on the HDD.
The other ways with using SSD as a cache layer related to using either ZFS or LVM. Since your system has only 2GB of RAM your only choice is LVM. But if you don’t have it initially, the conversion is pretty complicated and dangerous. The safe way (but very long) is to use LVM on a new disk, create PV, LV with SSD layer and migrate your current node to there.

The migration to LVM is possible in-place, if you have more free space than used.
Example with a virtual disk:

prepare a test lab disk and a random data

  1. Create a GPT partition table:
$ sudo parted /dev/loop2 mklabel gpt
$ sudo partprobe /dev/loop2
  1. Create a Primary partition
$ sudo parted /dev/loop2 mkpart primary ext4 1MiB 2.999GiB
  1. Format it to ext4
$ sudo mkfs -t ext4 /dev/loop2p1
  1. Create a mount folder
$ sudo mkdir /mnt/storj
  1. Mount a disk
$ sudo mount /dev/loop2p1 /mnt/storj
$ sudo chown $(id -u) /mnt/storj
  1. Copy the example file to that disk
$ cp disk1.raw /mnt/storj/
  1. make an md5sum file to check that the file is not corrupted (this is not necessary, but allows to check that everything went well)
$ pushd /mnt/storj
/mnt/storj ~
$ md5sum disk1.raw > disk1.raw.md5
  1. Checking:
$ md5sum -c disk1.raw.md5
disk1.raw: OK
$ popd
~
  1. The current state is your initial state to emulate a storagenode, but with only one file disk1.raw 1GiB in size. Here you need to stop and remove the storagenode container, but not in this test lab

Convert the disk with GPT to LVM on the fly

  1. unmount the disk, because ext4 doesn’t allow to shrink it online or you can resize your disk using GPart or KDE Partition Manager to free-up 1.1GiB of the disk space, then create a PV on it, and they will do this automatically, but we will continue in the CLI:
$ sudo umount /mnt/storj
  1. check the filesystem
$ sudo e2fsck -f /dev/loop2p1
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/loop2p1: 13/196608 files (0.0% non-contiguous), 31037/785920 blocks
  1. resize a filesystem
$ sudo resize2fs /dev/loop2p1 1900M
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/loop2p1 to 486400 (4k) blocks.
The filesystem on /dev/loop2p1 is now 486400 (4k) blocks long.
  1. shrink the partition (note - the size should be +1MiB)
$ sudo parted /dev/loop2 resizepart 1 1901MiB
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? y
Information: You may need to update /etc/fstab.
  1. check fs:
$ sudo e2fsck -f /dev/loop2p1
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/loop2p1: 13/122880 files (0.0% non-contiguous), 26411/486400 blocks
  1. mount it back (and here you can run your storagenode back)
$ sudo mount /dev/loop2p1 /mnt/storj
  1. check that our data is ok
$ pushd /mnt/storj
/mnt/storj ~
$ md5sum -c disk1.raw.md5
disk1.raw: OK
$ popd
~
  1. Create an LVM PV on the free space
$ sudo parted /dev/loop2 mkpart primary 1901MiB 100%
$ sudo parted /dev/loop2 set 2 lvm on
$ sudo partprobe /dev/loop2
  1. create a new PV
$ sudo pvcreate /dev/loop2p2
  Physical volume "/dev/loop2p2" successfully created.
  1. Create VG
$ sudo vgcreate vg0 /dev/loop2p2
  Volume group "vg0" successfully created
  1. Create LV
$ sudo lvcreate -l 100%FREE vg0
  Logical volume "lvol0" created.
  1. find our new lvm device
$ lsblk | grep lvm
  └─vg0-lvol0 254:0    0   1.1G  0 lvm
  1. format our new LVM volume
$ sudo mkfs -t ext4 /dev/mapper/vg0-lvol0
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 299008 4k blocks and 74880 inodes
Filesystem UUID: 13e90432-1592-4476-912e-c9ec7642bee0
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912

Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
  1. Mount a new lvm volume
$ sudo mkdir /mnt/storj-new
$ sudo mount /dev/mapper/vg0-lvol0 /mnt/storj-new
$ sudo chown $(id -u) /mnt/storj-new
  1. Migrate your data from /mnt/storj/ to /mnt/storj-new, but we will do only one sync for this test lab:
$ rsync -aP /mnt/storj/ /mnt/storj-new/
sending incremental file list
./
disk1.raw
  1,073,741,824 100%  104.56MB/s    0:00:09 (xfr#1, to-chk=2/4)
disk1.raw.md5
             44 100%    0.10kB/s    0:00:00 (xfr#2, to-chk=1/4)
  1. (here we need to stop and remove the storagenode container and make a last rsync with a --delete option and run the container back with a new path /mnt/storj-new). The node is now running and online using the new storage location.
  2. unmount the old location
$ sudo umount /mnt/storj
  1. create a new PV
$ sudo pvcreate /dev/loop2p1
WARNING: ext4 signature detected on /dev/loop2p1 at offset 1080. Wipe it? [y/n]: y
  Wiping ext4 signature on /dev/loop2p1.
  Physical volume "/dev/loop2p1" successfully created.
  1. extend vg0 with a new PV
$ sudo vgextend vg0 /dev/loop2p1
  Volume group "vg0" successfully extended
  1. forbid coming a new data to the second PV, all new data will go to the first PV
$ sudo pvchange -xn /dev/loop2p2
  Physical volume "/dev/loop2p2" changed
  1 physical volume changed / 0 physical volumes not changed
  1. move the data from the second PV to a first one on the fly (the storagenode will be online). This operation can be resumed, if there would be an interruption, it’s pretty safe.
$ sudo pvmove /dev/loop2p2
  /dev/loop2p2: Moved: 5.14%
  /dev/loop2p2: Moved: 100.00%
  1. remove the second PV after all data has been moved to a first PV
$ sudo vgreduce vg0 /dev/loop2p2
  Removed "/dev/loop2p2" from volume group "vg0"
$ sudo pvremove /dev/loop2p2
  Labels on physical volume "/dev/loop2p2" successfully wiped.
  1. remove the second partition and extend a first one
$ sudo parted /dev/loop2 rm 2
Information: You may need to update /etc/fstab.

$ sudo parted /dev/loop2 resizepart 1 100%
Information: You may need to update /etc/fstab.

$ sudo partprobe /dev/loop2
  1. extend PV
$ sudo pvresize /dev/loop2p1
  Physical volume "/dev/loop2p1" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized
  1. check names of our VG and LV
$ sudo lvs
  LV    VG  Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lvol0 vg0 -wi-ao---- 1.14g
  1. extend LV
$ sudo lvextend -l +100%FREE -r vg0/lvol0
  Size of logical volume vg0/lvol0 changed from 1.14 GiB (292 extents) to <3.00 GiB (767 extents).
  Logical volume vg0/lvol0 successfully resized.
resize2fs 1.47.0 (5-Feb-2023)
Filesystem at /dev/mapper/vg0-lvol0 is mounted on /mnt/storj-new; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/mapper/vg0-lvol0 is now 785408 (4k) blocks long.
  1. check the data
$ pushd /mnt/storj-new
/mnt/storj-new ~
$ md5sum -c disk1.raw.md5
disk1.raw: OK
$ popd
$ df -h /dev/mapper/vg0-lvol0
Filesystem             Size  Used Avail Use% Mounted on
/dev/mapper/vg0-lvol0  3.0G  1.1G  1.8G  37% /mnt/storj-new