写入由某些事件中断的数据 [英] writing of data interrupted by some event

查看:108
本文介绍了写入由某些事件中断的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个问题,但有些人要求更多信息。所以我提供更多信息。

I had this question but some people asked for more info. So I am providing more info.

我有一张智能卡和一个读卡器。用户可以随时从阅读器中删除该卡。
智能卡有不同的块(16字节),我可以写任何我想要的块。

I have a smart card and a reader. User can remove the card from the reader at any time. Smart card has different blocks (of 16 byte) and I can write in whichever block I want.

现在我有一个函数作为线程运行:

Now I have this function which runs as a thread:

3    void function (void *p)
4    {
5        if(smartCardRemoved)
6            doSmth();
7        else
8        {
9            // Smart card is inside the reader
10           writeDataToCard(handle, blockNr, data1);
11            blockNr++; 
12           writeDataToCard(handle, blockNr, data2); 
13           blockNr=12;
14           readDataFromCard(blockNr, credit);
15           credit--;
16           writeDataToCard(cardHandle, blockNr, credit);
        }
    }

data1 data2 基本上是时间戳,信用是卡上的信用。
现在的问题是。说步骤10和12执行,意味着时间戳是
写入卡。但现在,用户从读卡器中删除卡
- 这意味着步骤14,15,16将不会被执行 - 这是一个问题,我
,因为时间戳写入,但信用没有减少。这就像我说的
是一个问题。因此,如果执行步骤10和12,也必须执行步骤14,15和16。处理这个问题的方法是什么?

data1 and data2 are basically timestamps and credit is credit on the card. Now the problem is. Say steps 10 and 12 are executed, meaning timestamps are written to the card. But now, user removes the card from the reader - this means steps 14,15,16 will not be executed - and that is a problem for me because the timestamps were written but credit was not decremented. This as I said is a problem. So if steps 10 and 12 were executed steps 14, 15, and 16 MUST also be executed. What are the ways to deal with this?

ps。使用单一提交可能无法写入所有内容,但我需要检查。

ps. It may not be possible to write everything using single commit, though I need to check.

pps。现在我想到了,我想我可能有类似的问题,如果说第12步成功,但步骤15抛出异常或返回假。在这种情况下该怎么办?

pps. Now that I think of it, I think I may have similar issues if say step 12 is successful, but step 15 throws exception or returns false. What to do in such case?

我真的很感激周到和细心的回答。谢谢。

I would really appreciate thoughtful and careful answer. Thank you.

推荐答案

考虑使用提交日志,这是许多文件系统和数据库服务器使用的机制,以确保数据完整性在面临意外的断电,系统崩溃或设备连接故障时。

Consider using a commit journal, which is a mechanism used by many filesystems and database servers to ensure data integrity even in the face of unexpected power loss, system crashes, or device connection failures.

提交日志的基本思想是,在将数据写入实际块之前,你写下你要写入到其他块。然后,如果写操作中断,您可以查看提交日志并重播中断的完整写操作。这将使数据恢复到一致状态。

The basic idea of a commit journal is that before you write the data to the actual blocks, you write down what you are about to write to other blocks. Then, if the write operation is interrupted you can look at the commit journal and replay the complete write operation that was interrupted. This will bring the data back into a consistent state.

在卡上将N + 1块专用于此,其中N是要更改的块数。在这种情况下,看起来你正在改变五个块,所以你将需要在日志中的六个。

Dedicate N+1 blocks to this on the card, where N is the number of blocks you are changing. In this case is looks like you are changing five blocks, so you will need six in the journal. The sixth block is "state" to indicate if the actual write was incomplete.

例如,您可以这样布置六个日志块:

For example, you might lay out the six journal blocks like this:

Journal block: |  0  |  1  |  2  |  3  |  4  |   5   |
Contents:      | B10 | B12 | B15 | B16 | B17 | STATE |

状态块可以指示dirty或clean。用于这些状态的值不重要。 (你可以使用true或false,例如,我建议让他们的编译时常数,如 JOURNAL_STATE_DIRTY JOURNAL_STATE_CLEAN 所以其含义是清楚的。)

The state block can indicate "dirty" or "clean." Which values you use for these states is not important. (You can use true or false, for example. I would suggest making them compile-time constants like JOURNAL_STATE_DIRTY and JOURNAL_STATE_CLEAN so their meaning is clear.)

格式化卡时,状态块应初始化为干净。

The state block should be initialized to "clean" when a card is formatted.

操作的基本顺序如下:


  1. 将新数据写入五个日志块。

  2. 将状态块设置为dirty。

  3. 将新数据写入实际的目标块(10,12,15,16,17)。

  4. 将状态块设置为清除。

  1. Write the new data to the five journal blocks.
  2. Set the state block to dirty.
  3. Write the new data to the actual destination blocks (10, 12, 15, 16, 17).
  4. Set the state block to clean.

初始化卡时,首先要做的是检查状态是脏的。如果是,则通过在步骤3恢复写入操作来重放日志,除了在这种情况下您正在从日志块读取新数据。

When initializing the card, the very first thing you would do is check if the state is dirty. If it is, then replay the journal by resuming the write operation at step 3, except in this case you are reading the "new data" from the journal blocks.

如果操作在步骤2完成之前中断,状态块应该是干净的,并且不执行日志重放。

If the operation is interrupted before step 2 completes, the state block should be "clean" and no journal replay will be performed. The write will have wholly failed and the card will contain the old data, fully intact.

如果操作在步骤2完成后中断,则状态块将为脏状态,并且下次连接设备时将重播日志。实际的块10,12,15,16和17可能已损坏,但是重放日志将纠正这一点,结果是在重放日志之后块将具有正确的新值。

If the operation is interrupted after step 2 completes, the state block will be "dirty" and the journal will be replayed next time the device is connected. The actual blocks 10, 12, 15, 16, and 17 might be corrupted, but replaying the journal will correct this and the result is that the blocks will have the correct new values after the journal is replayed.

请注意,如果所有使用该卡的软件都能理解并实现此日志技术,则此方法只能奏效。如果用户在写入时删除卡,一个不知道日志的设备,它将使用损坏的数据。这不是你可以做的。

Note that this approach will only work well if all software that uses the card understands and implements this journal technique. If the user removes the card mid-write and takes it to a device that does not know about the journal, it will be using corrupted data. This is nothing you can do about this.

如果你想成为偏执狂,将另一个块用于包含五个数据块的校验和的日志。这将允许您在重放步骤期间检测日志数据是否损坏。在这种情况下,您可能会通知用户他们的卡已损坏,他们需要为其服务。

If you want to be extra-paranoid, dedicate another block to the journal that will contain a checksum of the five data blocks. This will allow you to detect during the replay step if the journal data is corrupt. In that case you might inform the user that their card has been corrupted and they need to have it serviced.

这篇关于写入由某些事件中断的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆