修复事件等待指定时间BUG;添加小文件完整性读写类

This commit is contained in:
gb 2024-02-18 17:26:02 +08:00
parent ac089c602e
commit 2a64a5073e
7 changed files with 275 additions and 53 deletions

View File

@ -379,6 +379,8 @@ void scanner_hw::thread_image_capture(bool paper_ready)
int attempt = 0;
while(paper_ready && scanning_ && attempt++ < 5)
{
mbev.first = -1;
mbev.second = 0;
if(mb_events_.take(mbev, true, to_lifter_)
&& mbev.first == MOTOR_BORD_EVENT_LIFTER_READY)
{
@ -386,7 +388,7 @@ void scanner_hw::thread_image_capture(bool paper_ready)
break;
}
else
utils::to_log(LOG_LEVEL_FATAL, "Wait Lifter event(%d - 0x%08x) before scanning failed.\n", mbev.first, mbev.second);
utils::to_log(LOG_LEVEL_FATAL, "Wait Lifter event before scanning failed, get event(%d - 0x%08x).\n", mbev.first, mbev.second);
motor_->start();
}
if(mbev.first == MOTOR_BORD_EVENT_LIFTER_READY)
@ -477,19 +479,19 @@ void scanner_hw::thread_image_capture(bool paper_ready)
// wait paper ...
while(auto_scan_)
{
mbev.first = -1;
mbev.second = 0;
if(mb_events_.take(mbev, true))
{
if(mbev.first == MOTOR_BORD_EVENT_PAPER_READY)
{
motor_->start();
printf("paper ready: %d-%x\n", mbev.first, mbev.second);
mb_events_.take(mbev, true, to_lifter_);
motor_->start();
break;
}
printf("motor-board event is %d\n", mbev.first);
printf("\tmotor-board event is %d\n", mbev.first);
}
}
printf("motor-board event is %d\n", mbev.first);
}
if(scanning_ && mbev.first != MOTOR_BORD_EVENT_LIFTER_READY && times == 0)

View File

@ -12,9 +12,12 @@
#define SIZE_MB(n) SIZE_KB((n) * 1024)
#define SIZE_GB(n) SIZE_MB((n) * 1024)
#define SEC_2_MS(s) ((s) * 1000)
#define MSEC_2_US(ms) ((ms) * 1000)
#define USEC_2_NS(us) ((long)(us) * 1000)
#define MSEC_2_US(ms) ((long)(ms) * 1000)
#define SEC_2_MS(s) ((long)(s) * 1000)
#define MSEC_2_NS(ms) USEC_2_NS(MSEC_2_US(ms))
#define SEC_2_US(s) MSEC_2_US(SEC_2_MS(s))
#define SEC_2_NS(s) USEC_2_NS(SEC_2_US(s))
#define MM_PER_INCH 25.4f
#define IS_DOUBLE_EQUAL(a, b) fabs((a) - (b)) < .000001

View File

@ -1991,8 +1991,19 @@ bool platform_event::wait(unsigned timeout)
to.tv_sec = time(nullptr);
}
#endif
//*/
to.tv_nsec += MSEC_2_NS(timeout);
to.tv_sec += to.tv_nsec / SEC_2_NS(1);
to.tv_nsec %= SEC_2_NS(1);
/*/
to.tv_sec += timeout / 1000;
to.tv_nsec += (long)((timeout % 1000) * 1000 * 1000);
to.tv_nsec += MSEC_2_NS(timeout % 1000);
if(to.tv_nsec >= SEC_2_NS(1))
{
to.tv_sec++;
to.tv_nsec -= SEC_2_NS(1);
}
////////*//////////////////
waited = sem_timedwait(&sem_, &to) == 0;
}
if (log_)
@ -2351,3 +2362,125 @@ int safe_thread::stop(const char* thread_name)
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// safe_file
safe_file::safe_file(const char* path)
{
set_file_path(path);
}
safe_file::~safe_file()
{}
uint32_t safe_file::checksum(const void* data, size_t bytes, uint32_t prev)
{
uint32_t chk = prev, mask[] = {0, 0x0ff, 0x0ffff, 0x0ffffff};
const uint32_t *d = (const uint32_t*)data;
for(int i = 0; i < bytes / 4; ++i)
chk ^= *d++;
chk ^= *d & mask[bytes % 4];
return chk;
}
std::string safe_file::load_with_check(const char* file, bool ignore_lost)
{
FILE* src = fopen(file, "rb");
std::string cont("");
if(src)
{
long l = 0;
fseek(src, 0, SEEK_END);
l = ftell(src);
fseek(src, 0, SEEK_SET);
if(l > sizeof(SFHEAD))
{
SFHEAD head;
fread(&head, 1, sizeof(head), src);
if(head.len == l - sizeof(head))
{
char buf[256] = {0};
int r = fread(buf, 1, sizeof(buf), src);
while(r > 0)
{
cont += std::string(buf, r);
r = fread(buf, 1, sizeof(buf), src);
}
uint32_t chk = checksum(&head, sizeof(head));
chk = checksum(cont.c_str(), cont.length(), chk);
if(chk)
{
utils::to_log(LOG_LEVEL_FATAL, "Checksum(%08x) of safe_file(%s) failed!\n", chk, file);
cont = "";
}
else
{
iotimes_ = head.iotimes;
}
}
else
{
utils::to_log(LOG_LEVEL_FATAL, "safe_file(%s) length(%d) is mismatched(%d)!\n", file, (int)l, head.len);
}
}
else
{
utils::to_log(LOG_LEVEL_FATAL, "safe_file(%s) length(%d) is too small!\n", file, (int)l);
}
fclose(src);
}
else if(!ignore_lost)
{
utils::to_log(LOG_LEVEL_FATAL, "open safe_file(%s) failed: %d(%s).\n", file, errno, strerror(errno));
}
return std::move(cont);
}
void safe_file::set_file_path(const char* path)
{
path_ = path ? path : "";
iotimes_ = 0;
}
std::string safe_file::load(void)
{
std::string cont(load_with_check((path_ + tmp_appendix_).c_str(), true));
if(cont.empty())
cont = load_with_check(path_.c_str(), false);
return std::move(cont);
}
int safe_file::save(const void* data, uint16_t bytes)
{
// io time ...
if(iotimes_ == 0)
{
load();
}
SFHEAD head;
FILE *dst = nullptr;
head.chksum = 0;
head.iotimes = ++iotimes_;
head.len = bytes;
head.time = time(nullptr);
head.chksum = checksum(&head, sizeof(head));
head.chksum = checksum(data, bytes, head.chksum);
dst = fopen((path_ + tmp_appendix_).c_str(), "wb");
if(!dst)
return errno;
fwrite(&head, 1, sizeof(head), dst);
fwrite(data, 1, bytes, dst);
fclose(dst);
return rename((path_ + tmp_appendix_).c_str(), path_.c_str());
}

View File

@ -482,3 +482,36 @@ public:
int start(std::function<void(void)> f, const char* thread_name, void* addr = nullptr);
int stop(const char* thread_name);
};
// Purpose: safe file ensure the integrity of small data files
//
// Format: (uint16_t)raw data len + (uint32_t)checksum + raw data
//
// Flow: when save, write into file 'name.new' first, and rename to 'name' at last
// when read, check 'name.new' first, and open name if '.new' not exists
class safe_file
{
typedef struct _sf_head // ensure this struct size be multiple of size uint32_t
{
uint32_t chksum;
uint32_t time;
uint64_t len : 16;
uint64_t iotimes : 48;
}SFHEAD, *LPSFHEAD;
const std::string tmp_appendix_ = ".new";
std::string path_;
uint64_t iotimes_ = 0;
uint32_t checksum(const void* data, size_t bytes, uint32_t prev = 0);
std::string load_with_check(const char* file, bool ignore_lost);
public:
safe_file(const char* path);
~safe_file();
public:
void set_file_path(const char* path);
std::string load(void);
int save(const void* data, uint16_t bytes);
};

View File

@ -403,6 +403,10 @@ static uint8_t qiaoting[] = {128, 32
}
};
#define TEST_PLATFORM_EVENT
#ifdef TEST_PLATFORM_EVENT
platform_event to__("to");
#endif
ui_mgr::ui_mgr() : disp_data_("lcd-msg")
{
utils::init_log(LOG_TYPE_FILE);
@ -428,10 +432,40 @@ ui_mgr::ui_mgr() : disp_data_("lcd-msg")
auto display = [this](void) -> void
{
#ifdef TEST_PLATFORM_EVENT
printf("\tdisplay thread starting, sleep 3000ms ...\n");
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
printf("\tdisplay thread trigger event ...\n");
to__.trigger();
#endif
thread_display();
};
#ifdef TEST_PLATFORM_EVENT
to__.enable_log(false);
#endif
disp_thrd_.start(display, "thread_display");
#ifdef TEST_PLATFORM_EVENT
// display thread starting, sleep 3000ms ...
// [2024-02-18 08:01:54.349173] try wait 001: Failure
// [2024-02-18 08:01:54.849311] try wait 002: Failure
// [2024-02-18 08:01:55.349411] try wait 003: Failure
// [2024-02-18 08:01:55.849550] try wait 004: Failure
// [2024-02-18 08:01:56.349645] try wait 005: Failure
// display thread trigger event ...
// [2024-02-18 08:01:56.849441] try wait 006: OK
// [2024-02-18 08:01:57.349550] try wait 007: Failure
// [2024-02-18 08:01:57.849659] try wait 008: Failure
int up = 10000;
for(int i = 0; i < up; ++i)
{
bool wait = to__.wait(500);
printf("[%s] try wait %03d: %s\n", utils::format_current_time().c_str(), i + 1, wait ? "OK" : "Failure");
if(wait)
up = i + 3;
}
#endif
auto statu = [this](devui::LPMSGSTREAM pack) -> void
{
if(pack->msg == devui::UI_STATUS_SCANNING)
@ -462,6 +496,10 @@ ui_mgr::ui_mgr() : disp_data_("lcd-msg")
disp_data_.save(dd, true);
}
}
else
{
perm_data_->save();
}
}
else if(pack->msg == devui::UI_STATUS_PAPER_CNT)
{

View File

@ -136,40 +136,42 @@ class ui_mgr : public refer
utils::create_folder(root_.c_str());
root_ += PATH_SEPARATOR;
char buf[1024] = {0}, *ptr = buf;
FILE *src = fopen((root_ + his_name_).c_str(), "rb");
int len = 0;
safe_file file((root_ + his_name_).c_str());
std::string cont(file.load());
char *ptr = &cont[0];
LPSPEEDTM pspt = nullptr;
if(src)
if(!cont.empty())
{
len = fread(buf, 1, sizeof(buf), src);
fclose(src);
history_cnt_ = *(uint64_t*)buf;
len -= sizeof(history_cnt_);
ptr = buf + sizeof(history_cnt_);
history_cnt_ = *(uint64_t*)ptr;
ptr += sizeof(history_cnt_);
pspt = (LPSPEEDTM)ptr;
for(int i = 0; i < len / sizeof(*pspt); ++i)
for(int i = 0; i < (cont.length() - sizeof(history_cnt_)) / sizeof(*pspt); ++i)
{
TIMES t = {0};
t.history = pspt[i].ms;
speed_times_[pspt[i].speed] = t;
}
}
src = fopen((root_ + rol_name_).c_str(), "rb");
if(src)
else
{
memset(buf, 0, sizeof(buf));
len = fread(buf, 1, sizeof(buf), src);
fclose(src);
roller_cnt_ = *(uint32_t*)buf;
// test data:
TIMES t = {0};
len -= sizeof(roller_cnt_);
ptr = buf + sizeof(roller_cnt_);
history_cnt_ = 711;
t.history = 0x65642;
speed_times_[816] = t;
}
file.set_file_path((root_ + rol_name_).c_str());
cont = file.load();
if(!cont.empty())
{
ptr = &cont[0];
roller_cnt_ = *(uint32_t*)ptr;
ptr += sizeof(roller_cnt_);
pspt = (LPSPEEDTM)ptr;
for(int i = 0; i < len / sizeof(*pspt); ++i)
for(int i = 0; i < (cont.length() - sizeof(roller_cnt_)) / sizeof(*pspt); ++i)
{
if(speed_times_.count(pspt[i].speed))
{
@ -178,11 +180,17 @@ class ui_mgr : public refer
else
{
TIMES t = {0};
t.roller = pspt[i].ms;
t.history = t.roller = pspt[i].ms;
speed_times_[pspt[i].speed] = t;
}
}
}
else
{
// test data:
roller_cnt_ = 257;
speed_times_[816].roller = 0x2e54b;
}
}
protected:
@ -209,6 +217,11 @@ class ui_mgr : public refer
speed_times_[speed_].roller += run_ms;
if(hiscnt)
*hiscnt = history_cnt_;
if(adden_ > 10)
{
save();
adden_ = 0;
}
return roller_cnt_;
}
@ -218,6 +231,8 @@ class ui_mgr : public refer
for(auto& v: speed_times_)
v.second.roller = 0;
save();
return roller_cnt_;
}
void set_speed(uint32_t speed)
@ -231,33 +246,31 @@ class ui_mgr : public refer
}
void save(void)
{
FILE *dst = fopen((root_ + his_name_).c_str(), "wb");
if(dst)
{
fwrite(&history_cnt_, 1, sizeof(history_cnt_), dst);
for(auto& v: speed_times_)
{
SPEEDTM stm = {0};
stm.speed = v.first;
stm.ms = v.second.history;
fwrite(&stm, 1, sizeof(stm), dst);
}
fclose(dst);
}
safe_file file((root_ + his_name_).c_str());
std::string cont((char*)&history_cnt_, sizeof(history_cnt_));
dst = fopen((root_ + rol_name_).c_str(), "wb");
if(dst)
for(auto& v: speed_times_)
{
fwrite(&roller_cnt_, 1, sizeof(roller_cnt_), dst);
for(auto& v: speed_times_)
SPEEDTM stm = {0};
stm.speed = v.first;
stm.ms = v.second.history;
cont += std::string((char*)&stm, sizeof(stm));
}
file.save(cont.c_str(), cont.length());
cont = std::string((char*)&roller_cnt_, sizeof(roller_cnt_));
for(auto& v: speed_times_)
{
if(v.second.roller)
{
SPEEDTM stm = {0};
stm.speed = v.first;
stm.ms = v.second.roller;
fwrite(&stm, 1, sizeof(stm), dst);
cont += std::string((char*)&stm, sizeof(stm));
}
fclose(dst);
}
file.set_file_path((root_ + rol_name_).c_str());
file.save(cont.c_str(), cont.length());
}
};
refer_guard<permanent_data> perm_data_;

View File

@ -60,8 +60,8 @@ add_packagedirs("sdk")
add_defines("BUILD_AS_DEVICE")
add_defines("VER_MAIN=2")
add_defines("VER_FAMILY=200")
add_defines("VER_DATE=20240208")
add_defines("VER_BUILD=2")
add_defines("VER_DATE=20240218")
add_defines("VER_BUILD=20")
target("conf")
set_kind("phony")