Understanding Transaction Capacity

Discussed in this topic: fd.transactioncapacityremaining.

Fd.transactioncapacityremaining can tell you how many changed sectors the transaction journal can still accommodate. The initial value of the fd.transactioncapacityremaining  (just after fd.transactionstart) depends on two factors, whichever is smaller:

  • The value of 16 (this is the absolute maximum).
  • Maxjournalsectors-1, where maxjournalsectors is the argument of the fd.formatj method.

The maxjournalsectors allocates the journal area of the flash disk. In this journal area, one sector is always needed for internal housekeeping, while other sectors cache the data sectors changed during the transaction. Therefore, if you want to achieve the maximum journal capacity (16), the journal must have at least 17 sectors in it. It is very important to use the maximum transaction memory capacity. The value of 16 is not random — it guarantees that you will always be able, within a single transaction, to change the data in two different files.

In practice, do set a mach higher journal size. This won't increase transaction memory, but it will prolong the life of the flash IC. Values in the 50-100 range are recommended.

14- PL_FD_STATUS_TRANSACTION_CAPACITY_EXCEEDED error will be generated if transaction capacity is exceeded by performing too many disk write operations within a single transaction. The disk will be dismounted (but not damaged) and all changes to the disk made within this failed transaction will be forgotten.

Disk operations and the number of sectors they may affect

So how many sectors may be changed during various disk operations? The table below provides the worst-case numbers.

Fd. object's method that changes disk data

Maximum number of journal entries used


FRT*2 + FAT*2 + DATA = 5

fd.rename, fd.setattributes

FRT*2 = 2

fd.delete, fd.setfilesize, fd.cutfromtop*

FRT*2+ FAT*X*2 = ?


FRT*2 + FAT*2*2 + DATA*2 = 8

* Executing these methods can potentially overflow the transaction journal.

And now, the explanation for the table data. It is based on the material from the Disk Area Allocation Details topic.

  • "FRT" means "one sector from the file records table". File records are changed when files are created, renamed, or deleted. They are also changed when the file size changes, or when your application sets new file attributes.
  • "FAT" — "one sector from the file allocation table". File allocation sectors change when files are created and when file sectors are allocated or released in accordance with changing file sizes.
  • "DATA" — "one sector from the data sectors area of the disk". Data sectors hold actual file data. They change when you write new data to files.
  • "FRT2" and "FAT2" are caused by sector leveling: changing one FAT or FRT sector actually means changing two sectors.
  • "DATA*2" means that two data sectors can change when you write some data to the disk. This is because a portion of this data may reside in one data sectors, and the rest — in another data sector.
  • "X" parameter represents the number of active FAT sectors that can potentially be affected by invoking the corresponding method.

Here is how to calculate the X parameter:

Supposing, the flash disk capacity (fd.capacity) is 1000 sectors. The FAT, then, must hold 1000 entries. Each FAT sector can hold 128 entries, so there will be 8 active FAT sectors (X = 8). Do not confuse this with the total number of sectors in the FAT area — it is at least twice this amount (because of sector leveling measures). "8" here represents the number of FAT sectors that are needed at any given time.

Fd.delete, fd.setfilesize, and fd.cutfromtop top have one thing in common: they can potentially cut a huge file (occupying the entire disk) to zero. In the process, X FAT sectors will be altered!

Therefore, for the disk with fd.capacity= 1000, executing these methods can potentially change 2+8*2=18 sectors. This is above the maximum journal capacity, which is 16! So, how to avoid 14- PL_FD_STATUS_TRANSACTION_CAPACITY_EXCEEDED error and still use transactions?

And the answer is: do it in stages. The following example deletes a very large file in a "safe" manner:

** Tibbo Basic **

dim i as byte

i=(fd.transactioncapacityremaining-1)/2 'this is how many FAT sectors we can change at once
i=i*128 'and this is how many data sectors we can cut from the file at once (one FAT sector holds 128 entries)

while fd.filesize>0

Not a direct sum total

The worst-case number of sectors that may be changed during a transaction is not the sum total of maximum numbers for each fd. object's method. In the example below, the maximum number of changed sectors is 9, not 10.

** Tibbo Basic **

fd.setdata("write some data to a file") 'up to 8 sectors changed, and this includes 2 change FRT sectors
fd.setattributes("ABC") 'FRT changes again, but for the same FRT record (this will use only 1 entry in the journal) 
fd.transactioncommit 'therefore, the total is up to 9

In this example, the worst-case number is 10, because we are working with 2 different files and their FRT records could be in different FRT sectors:

** Tibbo Basic **

fd.setdata("write some data to a file") 'up to 8 sectors changed for file #0
fd.setattributes("ABC") '2 FRT sectors changed for file #1 
fd.transactioncommit 'therefore, the total is up to 10