Table of Contents

About

PrimFS™ and PrimDrive™ introduce an unconventional hard-drive that is able to store data by accounting for three-dimensions. While conventional hard-drives use superposed disks, PrimDrive uses a cube that is physically sub-divided into smaller blocks called sectors. PrimFS and PrimDrive thus eliminate the need to have out-of-world databases such as MySQL which will always fail to match the uptime of the Virtual World. In other words, PrimFS and PrimDrive offer an alternative to creators that allow them to store customer data (for example, game statistics) in-world instead of outside of Second Life.

In Linden-based Virtual Worlds, notably Second Life, developers can use the API provided by Wizardry and Steamworks to store data onto the PrimDrive persistently, such that it will be available even after simulator or grid shutdowns. Ideally, the PrimDrive is designed to function while it is attached to an avatar, as a building-component for HUDs or worn components. However, the API also allows to convert a linked structure into a database, such that data can be stored in any object, even if the handsome design of the PrimDrive is not suitable for a given application.

ChangeLog

16 July 2015

  • Code cleanups and updates to key-value data.

2 February 2014

  • stomped a bug in the writing subroutine.

11 January 2014

  • added the ability to query how much space is available or occupied by data in a partition.
  • changed the highlighting colors and transparency such that primitives can stand out.
  • added a command interpreter for the full test harness script.
  • optimized functions.

7 January 2014

  • initial release.

Features

Operations

There are two sets of operations depending on context. The PrimFS set of functions manipulate the filesystem whilst the PrimDrive functions operate on the drive.

PrimFS

Function Parameters Description
wasPrimFSFormat start sector, end sector Formats a partition of the PrimDrive.
wasPrimFSWrite descriptor, value, start sector, end sector Writes a descriptor referencing some data in the indicated partition and returns the number of bytes written.
wasPrimFSRead descriptor, start sector, end sector Reads the data referenced by the descriptor.
wasPrimFSDelete descriptor, start sector, end sector Deletes the descriptor and its associated data from all sectors between the starting and ending sector.
wasPrimFSGetDescriptors start sector, end sector Returns descriptors found between the start and end sectors.
wasPrimFSGetUsedSpace start sector, end sector Returns the space used in a partition bounded by start sector and end sector.
wasPrimFSGetFreeSpace start sector, end sector Returns the free space in a partition bounded by start sector and end sector.

PrimDrive

Function Parameters Description
wasPrimDriveLED start sector, end sector Will highlight the amount of data in all sectors between the start and end sectors.

Tutorial

Similar to any data-storage device, the PrimDrive requires a PrimFS partition to be created. The PrimFS filesystem is independent of the PrimDrive such that all PrimFS functions operate using start and end sectors which are a logical demarcation of partitions. More precisely, regardless whether the cube-shaped drive is used, or whether the controller script is placed in any other linked object containing primitives, all filesystem operations will operate on the sectors specified by the programmer.

Running the following command in the root-primitive of any linked object (assuming, larger than 10 linked primitives):

llOwnerSay((string)wasPrimFSFormat(5, 10)); 

will format all linked primitives in the interval $[5,10]$ to the PrimFS filesystem, the PrimDrive being the set of linked primitives with the initialized filesystem. The initialized primitives of the filesystem are called sectors in PrimFS terminology - we chose this terminology because the word "sectors" implies a larger container than blocks and also does not really have too much to do with any other terminology used for data storage. In short, any primitives formatted to the PrimFS filesystem are called sectors and a PrimDrive is the set of sectors initialized to the PrimFS filesystem.

Canonically the sectors used by the PrimFS filesystem form a partition. The previous example creates a partition with 6 sectors formatted with the PrimFS filesystem. Formatting, is as the name implies, the procedure of initializing sectors to default values and has the consequence of deleting any data between the supplied sectors.

After a partition has been created, it can be used by the PrimFS set of functions to perform various operations. To write a string to the partition, we can perform:

string txt = "Good day!";
integer s = wasPrimFSWrite("greeting", txt, 5, 10);

which will write "Good day!" on some sector in interval $[5, 10]$ that is able to store the data and will store the number of written bytes in variable s. The actual sector that has been written to is masked by the implementation of the PrimFS filesystem however a check should always be performed whether the string could be written to the drive, for example by checking whether s is equal to the length of the string "Good day!".

In the above example, the first parameter supplied to wasPrimFSWrite, the string "greeting" is what PrimFS calls a descriptor and is essentially a named pointer to some data (sort of like a merge between filenames and low-level links, for the sake of simplicity). PrimFS will thus store data such as "Good day!" referenced by a descriptor.

Retrieving data from the drive is made by calling wasPrimFSRead with the descriptor as argument, depending on what data should be retrieved. Assuming that we have previously performed the operation in the examples above, the following call:

llOwnerSay(wasPrimFSRead("greeting", 5, 10));

will retrieve the data referenced by the descriptor "greeting" and tell the user "Good day!". Deleting is also a similar operation, it takes a descriptor as argument and deletes any data referenced by that descriptor, along with the descriptor from a partition bounded by the supplied numbers.

The following call:

llOwnerSay((string)wasPrimFSDelete("greeting", 5, 10));

will delete the greeting "Good day!", along with the descriptor "greeting" from the filesystem.

When browsing a partition, you want to see the filenames on the drive and that is what wasPrimFSGetDescriptors is for. It returns all the descriptors on the partition as a list. The following call:

list d = wasPrimFSGetDescriptors(5, 10);

will return a list containing "greeting" if it has not previously been deleted.

Discussion

Storing data in three dimensions instead of two allows for some helpful features, namely:

Wizardry and Steamworks uses key-value data as the underlying data representation. The simplicity is desirable such that sectors can hold as much data as possible without too much structure overhead - by contrast with llJson* functions, for example.

Due to the fact that each block is a physical object some interesting qualities can be implicitly observed, for instance:

Traditional drives go from the mathematical property of circles that have the maximal surface at the minimal perimiter. That is, no other shape can have a surface larger than a circle at a given perimeter.

Nevertheless, the idea of disks are far too immature for a 3D world where data could be stored on three axes instead of two.

Generalizing the PrimFS and PrimDrive to a real-adaptible scenario would be a matter of finding a shape that is closest to an inverse-sphere and then disposing sectors on its surface.

Obtaining the Prototype

Index