修复事件等待指定时间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; int attempt = 0;
while(paper_ready && scanning_ && attempt++ < 5) while(paper_ready && scanning_ && attempt++ < 5)
{ {
mbev.first = -1;
mbev.second = 0;
if(mb_events_.take(mbev, true, to_lifter_) if(mb_events_.take(mbev, true, to_lifter_)
&& mbev.first == MOTOR_BORD_EVENT_LIFTER_READY) && mbev.first == MOTOR_BORD_EVENT_LIFTER_READY)
{ {
@ -386,7 +388,7 @@ void scanner_hw::thread_image_capture(bool paper_ready)
break; break;
} }
else 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(); motor_->start();
} }
if(mbev.first == MOTOR_BORD_EVENT_LIFTER_READY) if(mbev.first == MOTOR_BORD_EVENT_LIFTER_READY)
@ -477,19 +479,19 @@ void scanner_hw::thread_image_capture(bool paper_ready)
// wait paper ... // wait paper ...
while(auto_scan_) while(auto_scan_)
{ {
mbev.first = -1;
mbev.second = 0;
if(mb_events_.take(mbev, true)) if(mb_events_.take(mbev, true))
{ {
if(mbev.first == MOTOR_BORD_EVENT_PAPER_READY) if(mbev.first == MOTOR_BORD_EVENT_PAPER_READY)
{ {
motor_->start();
printf("paper ready: %d-%x\n", mbev.first, mbev.second); printf("paper ready: %d-%x\n", mbev.first, mbev.second);
mb_events_.take(mbev, true, to_lifter_); motor_->start();
break; 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) 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_MB(n) SIZE_KB((n) * 1024)
#define SIZE_GB(n) SIZE_MB((n) * 1024) #define SIZE_GB(n) SIZE_MB((n) * 1024)
#define SEC_2_MS(s) ((s) * 1000) #define USEC_2_NS(us) ((long)(us) * 1000)
#define MSEC_2_US(ms) ((ms) * 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_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 MM_PER_INCH 25.4f
#define IS_DOUBLE_EQUAL(a, b) fabs((a) - (b)) < .000001 #define IS_DOUBLE_EQUAL(a, b) fabs((a) - (b)) < .000001

View File

@ -1990,9 +1990,20 @@ bool platform_event::wait(unsigned timeout)
utils::to_log(LOG_LEVEL_DEBUG, "clock_gettime failed: %d - %s\n", errno, strerror(errno)); utils::to_log(LOG_LEVEL_DEBUG, "clock_gettime failed: %d - %s\n", errno, strerror(errno));
to.tv_sec = time(nullptr); to.tv_sec = time(nullptr);
} }
#endif #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_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; waited = sem_timedwait(&sem_, &to) == 0;
} }
if (log_) if (log_)
@ -2350,4 +2361,126 @@ int safe_thread::stop(const char* thread_name)
} }
return ret; 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 start(std::function<void(void)> f, const char* thread_name, void* addr = nullptr);
int stop(const char* thread_name); 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") ui_mgr::ui_mgr() : disp_data_("lcd-msg")
{ {
utils::init_log(LOG_TYPE_FILE); utils::init_log(LOG_TYPE_FILE);
@ -428,10 +432,40 @@ ui_mgr::ui_mgr() : disp_data_("lcd-msg")
auto display = [this](void) -> void 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(); thread_display();
}; };
#ifdef TEST_PLATFORM_EVENT
to__.enable_log(false);
#endif
disp_thrd_.start(display, "thread_display"); 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 auto statu = [this](devui::LPMSGSTREAM pack) -> void
{ {
if(pack->msg == devui::UI_STATUS_SCANNING) if(pack->msg == devui::UI_STATUS_SCANNING)
@ -462,6 +496,10 @@ ui_mgr::ui_mgr() : disp_data_("lcd-msg")
disp_data_.save(dd, true); disp_data_.save(dd, true);
} }
} }
else
{
perm_data_->save();
}
} }
else if(pack->msg == devui::UI_STATUS_PAPER_CNT) 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()); utils::create_folder(root_.c_str());
root_ += PATH_SEPARATOR; root_ += PATH_SEPARATOR;
char buf[1024] = {0}, *ptr = buf; safe_file file((root_ + his_name_).c_str());
FILE *src = fopen((root_ + his_name_).c_str(), "rb"); std::string cont(file.load());
int len = 0; char *ptr = &cont[0];
LPSPEEDTM pspt = nullptr; LPSPEEDTM pspt = nullptr;
if(src) if(!cont.empty())
{ {
len = fread(buf, 1, sizeof(buf), src); history_cnt_ = *(uint64_t*)ptr;
fclose(src); ptr += sizeof(history_cnt_);
history_cnt_ = *(uint64_t*)buf;
len -= sizeof(history_cnt_);
ptr = buf + sizeof(history_cnt_);
pspt = (LPSPEEDTM)ptr; 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}; TIMES t = {0};
t.history = pspt[i].ms; t.history = pspt[i].ms;
speed_times_[pspt[i].speed] = t; speed_times_[pspt[i].speed] = t;
} }
} }
else
src = fopen((root_ + rol_name_).c_str(), "rb");
if(src)
{ {
memset(buf, 0, sizeof(buf)); // test data:
len = fread(buf, 1, sizeof(buf), src); TIMES t = {0};
fclose(src);
roller_cnt_ = *(uint32_t*)buf;
len -= sizeof(roller_cnt_); history_cnt_ = 711;
ptr = buf + sizeof(roller_cnt_); 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; 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)) if(speed_times_.count(pspt[i].speed))
{ {
@ -178,11 +180,17 @@ class ui_mgr : public refer
else else
{ {
TIMES t = {0}; TIMES t = {0};
t.roller = pspt[i].ms; t.history = t.roller = pspt[i].ms;
speed_times_[pspt[i].speed] = t; speed_times_[pspt[i].speed] = t;
} }
} }
} }
else
{
// test data:
roller_cnt_ = 257;
speed_times_[816].roller = 0x2e54b;
}
} }
protected: protected:
@ -209,6 +217,11 @@ class ui_mgr : public refer
speed_times_[speed_].roller += run_ms; speed_times_[speed_].roller += run_ms;
if(hiscnt) if(hiscnt)
*hiscnt = history_cnt_; *hiscnt = history_cnt_;
if(adden_ > 10)
{
save();
adden_ = 0;
}
return roller_cnt_; return roller_cnt_;
} }
@ -217,6 +230,8 @@ class ui_mgr : public refer
roller_cnt_ = 0; roller_cnt_ = 0;
for(auto& v: speed_times_) for(auto& v: speed_times_)
v.second.roller = 0; v.second.roller = 0;
save();
return roller_cnt_; return roller_cnt_;
} }
@ -231,33 +246,31 @@ class ui_mgr : public refer
} }
void save(void) void save(void)
{ {
FILE *dst = fopen((root_ + his_name_).c_str(), "wb"); safe_file file((root_ + his_name_).c_str());
if(dst) std::string cont((char*)&history_cnt_, sizeof(history_cnt_));
{
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);
}
dst = fopen((root_ + rol_name_).c_str(), "wb"); for(auto& v: speed_times_)
if(dst)
{ {
fwrite(&roller_cnt_, 1, sizeof(roller_cnt_), dst); SPEEDTM stm = {0};
for(auto& v: speed_times_) 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}; SPEEDTM stm = {0};
stm.speed = v.first; stm.speed = v.first;
stm.ms = v.second.roller; 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_; refer_guard<permanent_data> perm_data_;

View File

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