图片接收转储过程中的内存全部用tiny_buffer(支持文件映射方式,WIN平台还需要完善)

This commit is contained in:
gb 2022-06-01 11:04:10 +08:00
parent 33f057b5c0
commit b83a31c5e4
21 changed files with 729 additions and 436 deletions

View File

@ -111,232 +111,4 @@ public:
} }
}; };
#include <string.h>
typedef struct _img_header
{
int width;
int height;
int bits;
int channels;
int line_bytes;
unsigned bytes;
}IMH;
typedef struct _img
{
IMH header;
unsigned offset;
bool is_file; // when this is true, then the 'data' stores the full path of the file
void* fptr;
std::shared_ptr<std::vector<unsigned char>> data;
}IMGDT;
class image_data
{
private:
image_data(const image_data& rhs);
image_data& operator =(const image_data& rhs);
mutable std::mutex _mutex;
std::condition_variable _condvar;
deque<IMGDT> _queue;
bool isShutDown;
IMGDT tRet;
public:
image_data()
: _mutex()
, _condvar()
, _queue()
, isShutDown(false)
{
}
~image_data()
{
ShutDown();
std::cout << "blocking queue release" << std::endl;
}
void Clear()
{
lock_guard<mutex> lock(_mutex);
_condvar.notify_all();
_queue.clear();
}
void ShutDown()
{
isShutDown = true;
_condvar.notify_all();
_queue.clear();
}
bool IsShutDown()
{
return isShutDown;
}
void Put(const IMGDT task)
{
lock_guard<mutex> lock(_mutex);
if (!isShutDown)
{
{
_queue.push_back(task);
}
_condvar.notify_all();
}
}
bool put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes)
{
IMGDT img;
img.header.width = w;
img.header.height = h;
img.header.bits = bpp;
img.header.channels = channels;
img.header.line_bytes = line_bytes;
img.offset = 0;
img.header.bytes = bytes;
img.data.reset(new std::vector<unsigned char>(bytes));
if (!img.data.get())
return false;
img.is_file = false;
img.fptr = nullptr;
memcpy(img.data->data(), data, bytes);
Put(img);
return true;
}
bool put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes, const char* file)
{
IMGDT img;
img.header.width = w;
img.header.height = h;
img.header.bits = bpp;
img.header.channels = channels;
img.header.line_bytes = line_bytes;
img.offset = 0;
img.header.bytes = bytes;
img.is_file = true;
img.fptr = nullptr;
img.data.reset(new std::vector<unsigned char>(strlen(file) * 2));
if (!img.data.get())
return false;
strcpy((char*)&img.data->data()[0], file);
FILE* dst = fopen(file, "rw+b");
if (!dst)
return false;
fwrite(data, 1, bytes, dst);
fclose(dst);
img.fptr = fopen(file, "rb"); // open and keep it
if (!img.fptr)
{
remove(file);
return false;
}
Put(img);
return true;
}
IMGDT Take()
{
unique_lock<mutex> lock(_mutex);
if (_queue.size() <= 0)
_condvar.wait(lock);
if (isShutDown || _queue.empty())
{
return tRet;
}
IMGDT front(_queue.front());
_queue.pop_front();
return front;
}
IMGDT Front()
{
unique_lock<mutex> lock(_mutex);
if (_queue.size() <= 0)
_condvar.wait(lock);
if (isShutDown || _queue.empty())
{
return tRet;
}
IMGDT front(_queue.front());
return front;
}
bool front(IMH* header)
{
unique_lock<mutex> lock(_mutex);
if (_queue.size() <= 0)
_condvar.wait(lock);
if (isShutDown || _queue.empty())
{
return false;
}
memcpy(header, &_queue.front().header, sizeof(*header));
return true;
}
size_t Size() const
{
lock_guard<mutex> lock(_mutex);
return _queue.size();
}
void fetch_front(void* buf, int* len, bool* over)
{
if (Size() == 0)
*len = 0;
else
{
lock_guard<mutex> lock(_mutex);
if (_queue.front().is_file)
{
if (_queue.front().data->size() - _queue.front().offset <= *len)
{
*len = _queue.front().data->size() - _queue.front().offset;
fread(buf, 1, *len, (FILE*)_queue.front().fptr);
fclose((FILE*)_queue.front().fptr);
remove((const char*)_queue.front().data->data());
_queue.pop_front();
if (over)
*over = true;
}
else
{
fread(buf, 1, *len, (FILE*)_queue.front().fptr);
_queue.front().offset += *len;
if (over)
*over = false;
}
}
else
{
if (_queue.front().data->size() - _queue.front().offset <= *len)
{
*len = _queue.front().data->size() - _queue.front().offset;
memcpy(buf, _queue.front().data->data() + _queue.front().offset, *len);
_queue.pop_front();
if (over)
*over = true;
}
else
{
memcpy(buf, _queue.front().data->data() + _queue.front().offset, *len);
_queue.front().offset += *len;
if (over)
*over = false;
}
}
}
}
};
#endif #endif

View File

@ -7,6 +7,8 @@
#else #else
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -248,7 +250,7 @@ char* shared_memory::get_buf(void)
#else #else
int* h = (int*)&obj_; int* h = (int*)&obj_;
char* buf = (char*)shmat(*h, 0, 0); char* buf = (char*)shmat(*h, 0, 0);
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "shared memory %d buffer = %s, error = %d\n", *h, hg_log::format_ptr(buf).c_str(), errno); VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "shared memory %d tiny_buffer = %s, error = %d\n", *h, hg_log::format_ptr(buf).c_str(), errno);
#endif #endif
return buf; return buf;
@ -340,3 +342,407 @@ int shared_memory::write(const char* data, size_t len)
len_ = len; len_ = len;
release_buf(buf); release_buf(buf);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tiny_file_map ...
#ifdef WIN32
#define IS_VALID_MAP(map) !map
#else
#define IS_VALID_MAP(map) map != -1
#endif
tiny_file_map::tiny_file_map() : size_(0), map_(0), buf_(nullptr), file_(""), keep_f_(false)
{}
tiny_file_map::~tiny_file_map()
{
close();
}
int tiny_file_map::open(const char* file, unsigned int size, bool readonly)
{
close();
int ret = 0;
#ifdef WIN32
if (readonly)
{
HANDLE f = CreateFileA(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (f == INVALID_HANDLE_VALUE)
ret = GetLastError();
else
{
size_ = GetFileSize(f, NULL);
map_ = CreateFileMappingA(f, NULL, PAGE_READONLY, 0, 0, NULL);
if (map_)
{
buf_ = (unsigned char*)MapViewOfFile(map_, FILE_MAP_READ, 0, 0, 0);
if (!buf_)
{
ret = GetLastError();
CloseHandle(map_);
map_ = nullptr;
size_ = 0;
}
}
else
ret = GetLastError();
CloseHandle(f);
}
}
else
{
size_ = size;
HANDLE f = CreateFileA(file, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (f == INVALID_HANDLE_VALUE)
ret = GetLastError();
else
{
//SYSTEM_INFO si = { 0 };
//GetSystemInfo(&si);
//size += si.dwPageSize - 1;
//size /= si.dwPageSize;
//size *= si.dwPageSize;
DWORD wrote = SetFilePointer(f, size - 1, NULL, FILE_BEGIN);
if (wrote == size - 1)
WriteFile(f, "\0", 1, &wrote, NULL);
map_ = CreateFileMappingA(f, NULL, PAGE_READONLY, 0, size, NULL);
if (map_)
{
buf_ = (unsigned char*)MapViewOfFile(map_, FILE_MAP_READ, 0, 0, size);
if (!buf_)
ret = GetLastError();
}
else
ret = GetLastError();
CloseHandle(f);
if (ret)
{
keep_f_ = false;
close();
}
}
}
#else
if (readonly)
{
map_ = ::open(file, O_RDONLY);
if (IS_VALID_MAP(map_))
{
struct stat fsize;
if (fstat(map_, &fsize) >= 0)
size_ = size = fsize.st_size;
}
}
else
{
map_ = ::open(file, O_CREAT | O_RDWR);
if (IS_VALID_MAP(map_))
{
if (lseek(map_, size - 1, SEEK_SET) < 0)
{
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "set file size to %u - 1 bytes failed: %d\n", size, errno);
ret = errno;
::close(map_);
map_ = 0;
remove(file);
return ret;
}
if (write(map_, "0", 1) < 0)
{
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "set file size to %u bytes failed: %d\n", size, errno);
ret = errno;
::close(map_);
map_ = 0;
remove(file);
return ret;
}
}
}
if (IS_VALID_MAP(map_))
{
buf_ = (unsigned char*)mmap(nullptr, size, readonly ? PROT_READ : PROT_WRITE, MAP_SHARED, map_, 0);
if (buf_ == (unsigned char*)MAP_FAILED)
{
buf_ = nullptr;
ret = errno;
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "mmap(%u) = %d\n", size, ret);
size_ = 0;
if (!readonly)
remove(file);
}
::close(map_);
map_ = 0;
}
else
ret = errno;
#endif
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "map([%s]%s) = %d\n", readonly ? "R" : "RW", file, ret);
if (ret == 0)
file_ = file;
return ret;
}
void tiny_file_map::close(void)
{
if (buf_)
{
#ifdef WIN32
UnmapViewOfFile(buf_);
#else
munmap(buf_, size_);
#endif
buf_ = nullptr;
}
if (map_)
{
#ifdef WIN32
CloseHandle(map_);
#else
::close(map_);
#endif
map_ = 0;
}
if (!keep_f_ && !file_.empty())
remove(file_.c_str());
size_ = 0;
file_ = "";
keep_f_ = false;
}
void tiny_file_map::keep_file(bool keep)
{
keep_f_ = keep;
}
unsigned char* tiny_file_map::mapping_buffer(void)
{
return buf_;
}
std::string tiny_file_map::file(void)
{
return file_;
}
unsigned int tiny_file_map::size(void)
{
return size_;
}
bool tiny_file_map::swap(void)
{
bool ret = true;
if (buf_)
{
#ifdef WIN32
UnmapViewOfFile(buf_);
#else
munmap(buf_, size_);
#endif
buf_ = nullptr;
}
else if (IS_VALID_MAP(map_))
{
#ifdef WIN32
buf_ = (unsigned char*)MapViewOfFile(map_, FILE_MAP_READ, 0, 0, size_);
#else
buf_ = (unsigned char*)mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, map_, 0);
if (buf_ == (unsigned char*)MAP_FAILED)
{
buf_ == nullptr;
VLOG_MINI_2(LOG_LEVEL_FATAL, "Remap '%s' failed: %d\n", file_.c_str(), errno);
}
#endif
ret = buf_ != nullptr;
}
else
{
VLOG_MINI_2(LOG_LEVEL_FATAL, "Remap '%s' bug the handle is %d\n", file_.c_str(), map_);
ret = false;
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// memory or file mapping ...
tiny_buffer::tiny_buffer(unsigned int size
, const char* tmp_path
, const char* name_leading
, const char* ext
, unsigned int uniq_id)
: size_(size), buf_(nullptr)
{
init(tmp_path, name_leading, ext, uniq_id);
}
tiny_buffer::tiny_buffer(const char* src_file)
{
fmap_.open(src_file, 0, true);
buf_ = fmap_.mapping_buffer();
size_ = fmap_.size();
}
tiny_buffer::~tiny_buffer()
{
if (buf_)
{
if (fmap_.file().empty())
delete[] buf_;
else
fmap_.close();
}
}
void tiny_buffer::init(const char* tmp_path, const char* name_leading, const char* ext, unsigned int uniq_id)
{
try
{
buf_ = new unsigned char[size_];
memset(buf_, 0, size_);
}
catch (...)
{
std::string f(tmp_path);
char buf[128] = { 0 };
f += PATH_SEPARATOR;
f += name_leading ? name_leading : "mapf";
sprintf(buf, "_%05u.%s", uniq_id, ext ? ext : "tmp");
f += buf;
fmap_.open(f.c_str(), size_, false);
buf_ = fmap_.mapping_buffer();
}
// VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Acquire memory with bytes %u = %s\n", size_, hg_log::format_ptr(buf_).c_str());
}
unsigned int tiny_buffer::size(void)
{
return size_;
}
unsigned char* tiny_buffer::data(void)
{
return buf_;
}
void tiny_buffer::keep_file(bool keep)
{
fmap_.keep_file(keep);
}
std::string tiny_buffer::file(void)
{
return fmap_.file();
}
bool tiny_buffer::swap(void)
{
if (fmap_.file().empty())
return true;
bool ret = fmap_.swap();
buf_ = fmap_.mapping_buffer();
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// final_img_queue
final_img_queue::final_img_queue()
{}
final_img_queue::~final_img_queue()
{}
size_t final_img_queue::size(void)
{
std::lock_guard<std::mutex> lck(lock_);
return queue_.size();
}
void final_img_queue::clear(void)
{
std::lock_guard<std::mutex> lck(lock_);
queue_.clear();
}
bool final_img_queue::put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes
, const char* tmp_path, const char* name_leading, const char* ext, int ind)
{
IMGDT imgd;
bool ret = false;
imgd.header.bits = bpp;
imgd.header.bytes = bytes;
imgd.header.channels = channels;
imgd.header.height = h;
imgd.header.line_bytes = line_bytes;
imgd.header.width = w;
imgd.offset = 0;
imgd.data.reset(new tiny_buffer(bytes, tmp_path, name_leading, ext, ind));
if(imgd.data->data())
{
memcpy(imgd.data->data(), data, bytes);
if (imgd.data->swap())
{
std::lock_guard<std::mutex> lck(lock_);
queue_.push_back(imgd);
ret = true;
}
else
imgd.data.reset();
}
return ret;
}
bool final_img_queue::front(IMH* header)
{
std::lock_guard<std::mutex> lck(lock_);
if (queue_.size() == 0)
return false;
memcpy(header, &queue_[0].header, sizeof(*header));
return true;
}
void final_img_queue::fetch_front(void* buf, int* len, bool* over)
{
std::lock_guard<std::mutex> lck(lock_);
if (queue_.size() == 0)
{
if(len)
*len = 0;
if(over)
*over = true;
}
else
{
IMGDT& imgd = queue_[0];
if (imgd.offset == 0)
{
if (!imgd.data->swap())
{
*len = 0;
if (over)
*over = true;
VLOG_MINI_1(LOG_LEVEL_FATAL, "Reload final image '%s' failed!\n", imgd.data->file().c_str());
return;
}
}
if (imgd.offset + *len >= imgd.header.bytes)
*len = imgd.header.bytes - imgd.offset;
memcpy(buf, imgd.data->data() + imgd.offset, *len);
imgd.offset += *len;
if (imgd.offset >= imgd.header.bytes)
{
if (over)
*over = true;
queue_.erase(queue_.begin());
}
}
}

View File

@ -14,11 +14,14 @@
#include <semaphore.h> #include <semaphore.h>
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h> #include <sys/shm.h>
#include <sys/mman.h>
#define USB_TIMEOUT_INFINITE 0 #define USB_TIMEOUT_INFINITE 0
#endif #endif
#include <string> #include <string>
#include <vector>
#include <mutex> #include <mutex>
#include <memory>
class platform_event class platform_event
@ -125,4 +128,88 @@ public:
bool is_first(void); bool is_first(void);
std::string read(void); std::string read(void);
int write(const char* data, size_t len); int write(const char* data, size_t len);
};
// buffer
class tiny_file_map
{
unsigned int size_;
#ifdef WIN32
HANDLE map_;
#else
int map_;
#endif
unsigned char *buf_;
std::string file_;
bool keep_f_;
public:
tiny_file_map();
~tiny_file_map();
public:
int open(const char* file, unsigned int size, bool readonly);
void close(void);
void keep_file(bool keep);
unsigned char* mapping_buffer(void);
std::string file(void);
unsigned int size(void);
// mapping if unmapped; or unmapping if mapped
bool swap(void);
};
class tiny_buffer
{
unsigned int size_;
unsigned char *buf_;
tiny_file_map fmap_;
void init(const char* tmp_path, const char* name_leading, const char* ext, unsigned int uniq_id);
public:
tiny_buffer(unsigned int size, const char* tmp_path, const char* name_leading, const char* ext, unsigned int uniq_id);
tiny_buffer(const char* src_file);
~tiny_buffer();
public:
unsigned int size(void);
unsigned char* data(void);
void keep_file(bool keep);
std::string file(void);
// mapping if unmapped; or unmapping if mapped
bool swap(void);
};
typedef struct _img_header
{
int width;
int height;
int bits;
int channels;
int line_bytes;
unsigned bytes;
}IMH;
typedef struct _img
{
IMH header;
unsigned offset;
std::shared_ptr<tiny_buffer> data;
}IMGDT;
class final_img_queue
{
mutable std::mutex lock_;
std::vector<IMGDT> queue_;
public:
final_img_queue();
~final_img_queue();
public:
size_t size(void);
void clear(void);
bool put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes
, const char* tmp_path, const char* name_leading, const char* ext, int ind);
bool front(IMH* header);
void fetch_front(void* buf, int* len, bool* over);
}; };

View File

@ -95,9 +95,9 @@ hg_scanner::hg_scanner(ScannerSerial serial
{ {
final_path_ = hg_log::ini_get("paths", "final_img"); final_path_ = hg_log::ini_get("paths", "final_img");
if(final_path_.empty()) if(final_path_.empty())
final_path_ = g_module_path + "imgs"; final_path_ = hg_log::get_scanner_path() + "imgs";
if (hg_log::create_folder(final_path_.c_str())) if (hg_log::create_folder(final_path_.c_str()))
final_path_ += "/"; final_path_ += PATH_SEPARATOR;
else else
final_path_ = ""; final_path_ = "";
@ -187,12 +187,12 @@ int hg_scanner::save_2_tempory_file(std::shared_ptr<std::vector<char>> data, std
FILE* dst = nullptr; FILE* dst = nullptr;
int ret = SCANNER_ERR_OK; int ret = SCANNER_ERR_OK;
sprintf(head, "scan_%06u", index); sprintf(head, "usb_%05u", index);
file = hg_scanner::temporary_file((char*)".jpg", (char*)head); if(!path_file || path_file->empty())
dst = fopen(file.c_str(), "wb+"); file = hg_scanner::temporary_file((char*)".jpg", (char*)head);
dst = fopen(file.c_str(), "wb");
if (dst) if (dst)
{ {
ENOSPC; EROFS; strerror(errno);
size_t wrote = fwrite(data->data(), 1, data->size(), dst); size_t wrote = fwrite(data->data(), 1, data->size(), dst);
if (wrote == data->size()) if (wrote == data->size())
{ {
@ -670,8 +670,8 @@ void hg_scanner::thread_handle_image_process(void)
{ {
while (run_ && !user_cancel_) while (run_ && !user_cancel_)
{ {
std::shared_ptr<std::vector<char>> buffer; std::shared_ptr<tiny_buffer> tiny_buffer;
if (imgs_.Size() == 0 && paths_.Size() == 0) if (imgs_.Size() == 0)
{ {
if (wait_usb_.is_waiting()) if (wait_usb_.is_waiting())
break; break;
@ -680,39 +680,13 @@ void hg_scanner::thread_handle_image_process(void)
continue; continue;
} }
if (is_to_file()) tiny_buffer = imgs_.Take();
{ if(tiny_buffer->swap())
std::string file(paths_.Take()); image_process(tiny_buffer);
FILE* src = fopen(file.c_str(), "rb+");
if (src)
{
unsigned length = 0;
fseek(src, 0, SEEK_END);
length = ftell(src);
fseek(src, 0, SEEK_SET);
buffer = aquire_memory((int)length, false);
if (!buffer.get())
{
status_ = SCANNER_ERR_INSUFFICIENT_MEMORY;
break;
}
fread(buffer->data(), 1, length, src);
fclose(src);
remove(file.c_str());
}
else
{
VLOG_MINI_1(LOG_LEVEL_FATAL, "FATAL: open tempory image file '%s' failed.\n", file.c_str());
}
}
else else
{ {
buffer = imgs_.Take(); VLOG_MINI_1(LOG_LEVEL_FATAL, "Reload USB data '%s' failed!\n", tiny_buffer->file().c_str());
} }
image_process(buffer);
} }
} }
@ -720,16 +694,13 @@ void hg_scanner::working_begin(void*)
{ {
final_img_index_ = 0; final_img_index_ = 0;
notify_ui_working_status(STATU_DESC_SCAN_WORKING, SANE_EVENT_WORKING, SCANNER_ERR_OK); notify_ui_working_status(STATU_DESC_SCAN_WORKING, SANE_EVENT_WORKING, SCANNER_ERR_OK);
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "[%s] scanning ...\n", hg_log::current_time().c_str());
} }
void hg_scanner::working_done(void*) void hg_scanner::working_done(void*)
{ {
imgs_.Clear(); imgs_.Clear();
if(user_cancel_) if(user_cancel_)
final_imgs_.Clear(); final_imgs_.clear();
while (paths_.Size())
{
remove(paths_.Take().c_str());
}
switch (status_) switch (status_)
{ {
@ -798,15 +769,13 @@ void hg_scanner::working_done(void*)
break; break;
} }
//notify_ui_working_status(STATU_DESC_SCAN_STOPPED, SANE_EVENT_SCAN_FINISHED, status_);
if (test_1_paper_) if (test_1_paper_)
{ {
LOG_INFO(LOG_LEVEL_DEBUG_INFO, "scanning mode: finished testing ONE paper, restore to normal scanning.\n"); LOG_INFO(LOG_LEVEL_DEBUG_INFO, "scanning mode: finished testing ONE paper, restore to normal scanning.\n");
} }
else else
{ {
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "scanned %d picture(s) and finished with error %s.\n", final_img_index_, hg_scanner_err_name(status_)); VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "[%s] scanned %d picture(s) and finished with error %s.\n", hg_log::current_time().c_str(), final_img_index_, hg_scanner_err_name(status_));
} }
test_1_paper_ = false; test_1_paper_ = false;
@ -904,7 +873,7 @@ int hg_scanner::setting_help(void* data)
#ifdef WIN32 #ifdef WIN32
com = ""; com = "";
helpfile.insert(0, g_module_path); helpfile.insert(0, hg_log::get_scanner_path());
FILE* src = fopen(helpfile.c_str(), "rb"); FILE* src = fopen(helpfile.c_str(), "rb");
if (src) if (src)
fclose(src); fclose(src);
@ -1686,7 +1655,7 @@ int hg_scanner::try_third_app_handle_start(bool& handled)
while (wait_usb_result_.try_wait()) while (wait_usb_result_.try_wait())
std::this_thread::sleep_for(std::chrono::milliseconds(3)); std::this_thread::sleep_for(std::chrono::milliseconds(3));
if (!wait_img_.is_waiting() || !wait_usb_.is_waiting() || final_imgs_.Size()) if (!wait_img_.is_waiting() || !wait_usb_.is_waiting() || final_imgs_.size())
ret = SCANNER_ERR_OK; ret = SCANNER_ERR_OK;
else if (final_img_index_) else if (final_img_index_)
{ {
@ -1713,40 +1682,18 @@ int hg_scanner::try_third_app_after_start(int err)
return err; return err;
} }
std::shared_ptr<std::vector<char>> hg_scanner::aquire_memory(int size, bool from_usb) std::shared_ptr<tiny_buffer> hg_scanner::aquire_memory(int size, bool from_usb)
{ {
std::shared_ptr<std::vector<char>> mem; std::string lead(from_usb ? "usb" : "imgp"), ext(from_usb ? "jpg" : "dat");
unsigned int ind = from_usb ? usb_img_index_ : final_img_index_;
std::shared_ptr<tiny_buffer> mem(new tiny_buffer(size, final_path_.c_str(), lead.c_str(), ext.c_str(), ind));
try if (!mem->data())
{
mem.reset(new std::vector<char>(size));
}
catch (...)
{ {
mem.reset(); mem.reset();
VLOG_MINI_1(LOG_LEVEL_FATAL, "Allocate memory of bytes %u failed!\n", size); LOG_INFO(LOG_LEVEL_FATAL, "Can't aquire enough memory, working must be stopped!\n");
} notify_ui_working_status(STATU_DESC_SCANNER_ERR_INSUFFICIENT_MEMORY, SANE_EVENT_ERROR, SCANNER_ERR_INSUFFICIENT_MEMORY);
stop();
if (!mem.get())
{
if (from_usb && final_imgs_.Size())
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
try
{
mem.reset(new std::vector<char>(size));
}
catch (...)
{
mem.reset();
VLOG_MINI_1(LOG_LEVEL_FATAL, "Allocate memory of bytes %u failed secondary after 10 milliseconds!\n", size);
}
}
if (!mem.get())
{
LOG_INFO(LOG_LEVEL_FATAL, "Can't aquire enough memory, working must be stopped!\n");
stop();
}
} }
return mem; return mem;
@ -1824,30 +1771,22 @@ void hg_scanner::copy_to_sane_image_header(SANE_Parameters* header, int w, int h
header->lines = h; header->lines = h;
header->bytes_per_line = line_bytes; header->bytes_per_line = line_bytes;
} }
int hg_scanner::save_usb_data(std::shared_ptr<std::vector<char>> data) int hg_scanner::save_usb_data(std::shared_ptr<tiny_buffer> data)
{ {
int ret = SCANNER_ERR_OK; int ret = SCANNER_ERR_OK;
usb_img_index_++; usb_img_index_++;
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "USB read one picture with %u bytes\n", data->size()); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "USB read one picture with %u bytes\n", data->size());
if (is_to_file()) if (!data->swap())
{ {
std::string file(""); ret = SCANNER_ERR_OPEN_FILE_FAILED;
ret = hg_scanner::save_2_tempory_file(data, &file, usb_img_index_);
if (ret == SCANNER_ERR_OK)
paths_.Put(file);
} }
else else
{ {
imgs_.Put(data); imgs_.Put(data);
if (wait_img_.is_waiting())
#ifdef SAVE_TO_FILE wait_img_.notify();
hg_scanner::save_2_tempory_file(data, NULL, usb_img_index_);
#endif
} }
if (wait_img_.is_waiting())
wait_img_.notify();
return ret; return ret;
} }
@ -1856,8 +1795,7 @@ int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf)
std::string bw(""); std::string bw("");
final_img_index_++; final_img_index_++;
//if (image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE) if (image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE)
if(img_conf_.pixtype == 0)
{ {
int old = head->line_bytes; int old = head->line_bytes;
bw = bmp_821((unsigned char*)buf, head->width, head->height, &head->line_bytes, async_io_); bw = bmp_821((unsigned char*)buf, head->width, head->height, &head->line_bytes, async_io_);
@ -1877,25 +1815,11 @@ int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf)
return ui_ev_cb_((scanner_handle)this, SANE_EVENT_IMAGE_OK, &img, &final_img_index_, NULL); return ui_ev_cb_((scanner_handle)this, SANE_EVENT_IMAGE_OK, &img, &final_img_index_, NULL);
} }
if (resolution_ <= 300 && final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes)) if (final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes
, final_path_.c_str(), "final", "dat", final_img_index_))
return SCANNER_ERR_OK; return SCANNER_ERR_OK;
else else
{ return SCANNER_ERR_INSUFFICIENT_MEMORY;
// try file ...
char name[40] = { 0 };
sprintf(name, "img_%05d.dat", final_img_index_);
if (resolution_ <= 300)
{
VLOG_MINI_2(LOG_LEVEL_WARNING, "Memory(%u bytes) allocating failed when save final image, try save to file: %s\n", head->total_bytes, (final_path_ + name).c_str());
}
if(!final_path_.empty() &&
final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes
, (final_path_ + name).c_str()))
return SCANNER_ERR_OK;
else
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
} }
int hg_scanner::is_running(void) int hg_scanner::is_running(void)
{ {
@ -2247,10 +2171,10 @@ int hg_scanner::get_image_info(SANE_Parameters* ii)
bzero(&imh, sizeof(imh)); bzero(&imh, sizeof(imh));
bzero(ii, sizeof(*ii)); bzero(ii, sizeof(*ii));
while ((!wait_img_.is_waiting() || !wait_usb_.is_waiting()) && final_imgs_.Size() <= 0) while ((!wait_img_.is_waiting() || !wait_usb_.is_waiting()) && final_imgs_.size() <= 0)
this_thread::sleep_for(chrono::milliseconds(10)); this_thread::sleep_for(chrono::milliseconds(10));
if (final_imgs_.Size() <= 0) if (final_imgs_.size() <= 0)
ret = SCANNER_ERR_NO_DATA; ret = SCANNER_ERR_NO_DATA;
else else
{ {
@ -2301,7 +2225,7 @@ int hg_scanner::read_image_data(unsigned char* buf, int* len)
return SCANNER_ERR_INSUFFICIENT_MEMORY; return SCANNER_ERR_INSUFFICIENT_MEMORY;
} }
if (final_imgs_.Size() > 0) if (final_imgs_.size() > 0)
{ {
int fetch = *len; int fetch = *len;
bool over = false; bool over = false;

View File

@ -210,7 +210,7 @@ protected:
virtual int set_setting_value(int setting_no, void* data, int len); virtual int set_setting_value(int setting_no, void* data, int len);
virtual int on_scanner_closing(bool force); virtual int on_scanner_closing(bool force);
virtual void thread_handle_usb_read(void) = 0; virtual void thread_handle_usb_read(void) = 0;
virtual void image_process(std::shared_ptr<std::vector<char>>& buff) = 0; virtual void image_process(std::shared_ptr<tiny_buffer>& buff) = 0;
protected: protected:
volatile bool run_; volatile bool run_;
@ -251,25 +251,24 @@ protected:
SCANCONF img_conf_; //此参数外部不做任何改变请在writedown_image_configuration做修改 SCANCONF img_conf_; //此参数外部不做任何改变请在writedown_image_configuration做修改
std::string img_type_; std::string img_type_;
image_data final_imgs_; // JPG ... final_img_queue final_imgs_; // JPG ...
unsigned int usb_img_index_; unsigned int usb_img_index_;
unsigned int final_img_index_; unsigned int final_img_index_;
std::string final_path_; std::string final_path_;
BlockingQueue<std::shared_ptr<std::vector<char>>> imgs_; BlockingQueue<std::shared_ptr<tiny_buffer>> imgs_;
BlockingQueue<std::string> paths_;
void init_settings(const char* json_setting_text); void init_settings(const char* json_setting_text);
int on_scann_error(int err); // 返回“0”忽略错误继续执行其它值则停止后续工作 int on_scann_error(int err); // 返回“0”忽略错误继续执行其它值则停止后续工作
int try_third_app_handle_start(bool& handled); int try_third_app_handle_start(bool& handled);
int try_third_app_after_start(int err); int try_third_app_after_start(int err);
std::shared_ptr<std::vector<char>> aquire_memory(int size, bool from_usb = true); std::shared_ptr<tiny_buffer> aquire_memory(int size, bool from_usb = true);
// callback to ui ... // callback to ui ...
int notify_ui_working_status(const char* msg, int ev = SANE_EVENT_STATUS, int status = SCANNER_ERR_OK); int notify_ui_working_status(const char* msg, int ev = SANE_EVENT_STATUS, int status = SCANNER_ERR_OK);
bool waiting_for_memory_enough(unsigned need_bytes); bool waiting_for_memory_enough(unsigned need_bytes);
void copy_to_sane_image_header(SANE_Parameters* header, int w, int h, int line_bytes, int channels, int bits); void copy_to_sane_image_header(SANE_Parameters* header, int w, int h, int line_bytes, int channels, int bits);
int save_usb_data(std::shared_ptr<std::vector<char>> data); int save_usb_data(std::shared_ptr<tiny_buffer> data);
int save_final_image(hg_imgproc::LPIMGHEAD head, void* buf); int save_final_image(hg_imgproc::LPIMGHEAD head, void* buf);
enum thread_running enum thread_running

View File

@ -473,14 +473,14 @@ int hg_scanner_200::stop(void)
user_cancel_ = true; user_cancel_ = true;
if (ret == SCANNER_ERR_DEVICE_BUSY) if (ret == SCANNER_ERR_DEVICE_BUSY)
{ {
LOG_INFO(LOG_LEVEL_DEBUG_INFO,"stop status is busy\r\n"); LOG_INFO(LOG_LEVEL_DEBUG_INFO,"stop status is busy\r\n");
std::this_thread::sleep_for(std::chrono::milliseconds(2000)); std::this_thread::sleep_for(std::chrono::milliseconds(2000));
} }
else if (ret == SCANNER_ERR_OK) else if (ret == SCANNER_ERR_OK)
{ {
status_ = SCANNER_ERR_DEVICE_STOPPED; status_ = SCANNER_ERR_DEVICE_STOPPED;
} }
final_imgs_.Clear(); final_imgs_.clear();
return status_; return status_;
} }
@ -550,7 +550,7 @@ int hg_scanner_200::get_img_data(unsigned int bytes)
ret = SCANNER_ERR_OK, ret = SCANNER_ERR_OK,
index = 0, index = 0,
block = total; block = total;
std::shared_ptr<std::vector<char >> imagedata(aquire_memory(total)); std::shared_ptr<tiny_buffer> imagedata(aquire_memory(total));
if (!imagedata.get()) if (!imagedata.get())
return SCANNER_ERR_INSUFFICIENT_MEMORY; return SCANNER_ERR_INSUFFICIENT_MEMORY;
@ -571,7 +571,7 @@ int hg_scanner_200::get_img_data(unsigned int bytes)
if (total < block) if (total < block)
block = total; block = total;
ret = io_->read_bulk(imagedata->data() + index,&block); ret = io_->read_bulk(imagedata->data() + index, &block);
io_->set_timeout(500); //不能删除可能会导致IO超时 io_->set_timeout(500); //不能删除可能会导致IO超时
if (ret != SCANNER_ERR_OK) if (ret != SCANNER_ERR_OK)
break; break;
@ -587,7 +587,7 @@ int hg_scanner_200::get_img_data(unsigned int bytes)
return ret; return ret;
} }
void hg_scanner_200::image_process(std::shared_ptr<std::vector<char>>& buffer) void hg_scanner_200::image_process(std::shared_ptr<tiny_buffer>& buffer)
{ {
int ret = SCANNER_ERR_OK; int ret = SCANNER_ERR_OK;
hg_imgproc::IMGPRCPARAM param; hg_imgproc::IMGPRCPARAM param;

View File

@ -26,7 +26,7 @@ class hg_scanner_200 : public hg_scanner
protected: protected:
virtual int on_scanner_closing(bool force) override; virtual int on_scanner_closing(bool force) override;
virtual void thread_handle_usb_read(void) override; virtual void thread_handle_usb_read(void) override;
virtual void image_process(std::shared_ptr<std::vector<char>>& buff) override; virtual void image_process(std::shared_ptr<tiny_buffer>& buff) override;
virtual int on_color_mode_changed(int& color_mode); // COLOR_MODE_xxx virtual int on_color_mode_changed(int& color_mode); // COLOR_MODE_xxx

View File

@ -620,7 +620,7 @@ void hg_scanner_239::init_version(void)
else else
is_kernelsnap_211209_ = false; is_kernelsnap_211209_ = false;
} }
void hg_scanner_239::image_process(std::shared_ptr<std::vector<char>>& buff) void hg_scanner_239::image_process(std::shared_ptr<tiny_buffer>& buff)
{ {
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Process image with %u bytes content ...\n", buff->size()); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Process image with %u bytes content ...\n", buff->size());
@ -1000,7 +1000,7 @@ int hg_scanner_239::read_one_image_from_usb(void)
ret = status_; ret = status_;
else else
{ {
std::shared_ptr<std::vector<char>> buf(aquire_memory(total)); std::shared_ptr<tiny_buffer> buf(aquire_memory(total));
if (!buf.get()) if (!buf.get())
return SCANNER_ERR_INSUFFICIENT_MEMORY; return SCANNER_ERR_INSUFFICIENT_MEMORY;
@ -1701,17 +1701,13 @@ int hg_scanner_239::stop(void)
user_cancel_ = true; user_cancel_ = true;
ret = write_command(SC_STOP); ret = write_command(SC_STOP);
io_->set_timeout(500); io_->set_timeout(500);
final_imgs_.Clear(); final_imgs_.clear();
return status_; return status_;
} }
int hg_scanner_239::reset(void) int hg_scanner_239::reset(void)
{ {
final_imgs_.Clear(); final_imgs_.clear();
while (paths_.Size() > 0)
remove(paths_.Take().c_str());
discard_all_images(); discard_all_images();
return status_; return status_;

View File

@ -72,7 +72,7 @@ protected:
virtual void on_device_reconnected(void) override; virtual void on_device_reconnected(void) override;
virtual int on_scanner_closing(bool force) override; virtual int on_scanner_closing(bool force) override;
virtual void thread_handle_usb_read(void) override; virtual void thread_handle_usb_read(void) override;
virtual void image_process(std::shared_ptr<std::vector<char>>& buff) override; virtual void image_process(std::shared_ptr<tiny_buffer>& buff) override;
public: public:
hg_scanner_239(const char* dev_name, int pid,usb_io* io); hg_scanner_239(const char* dev_name, int pid,usb_io* io);

View File

@ -322,7 +322,7 @@ void hg_scanner_300::thread_handle_usb_read(void)
if (ret == SCANNER_ERR_OK && usb.u32_Count > 0) if (ret == SCANNER_ERR_OK && usb.u32_Count > 0)
{ {
int totalNum = usb.u32_Count; int totalNum = usb.u32_Count;
std::shared_ptr<std::vector<char >> imagedata(aquire_memory(totalNum)); std::shared_ptr<tiny_buffer> imagedata(aquire_memory(totalNum));
if (!imagedata.get()) if (!imagedata.get())
{ {
@ -425,7 +425,7 @@ int hg_scanner_300::stop(void)
{ {
status_ = SCANNER_ERR_DEVICE_STOPPED; status_ = SCANNER_ERR_DEVICE_STOPPED;
} }
final_imgs_.Clear(); final_imgs_.clear();
return status_; return status_;
} }
@ -491,7 +491,7 @@ int hg_scanner_300::get_scanner_status(USBCB &usb)
scanner_err code = settingsdsp_300::device_status_to_hg_err(usb.u32_Data); scanner_err code = settingsdsp_300::device_status_to_hg_err(usb.u32_Data);
return code ; return code ;
} }
int hg_scanner_300::get_img_data(std::shared_ptr<std::vector<char>> &imagedata) int hg_scanner_300::get_img_data(std::shared_ptr<tiny_buffer> &imagedata)
{ {
int total = imagedata->size(), int total = imagedata->size(),
ret = SCANNER_ERR_OK, ret = SCANNER_ERR_OK,
@ -535,7 +535,7 @@ int hg_scanner_300::get_img_data(std::shared_ptr<std::vector<char>> &imagedata)
return ret; return ret;
} }
void hg_scanner_300::image_process(std::shared_ptr<std::vector<char>>& buffer) void hg_scanner_300::image_process(std::shared_ptr<tiny_buffer>& buffer)
{ {
int ret = SCANNER_ERR_OK; int ret = SCANNER_ERR_OK;
hg_imgproc::IMGPRCPARAM param; hg_imgproc::IMGPRCPARAM param;

View File

@ -25,7 +25,7 @@ class hg_scanner_300 : public hg_scanner
protected: protected:
virtual int on_scanner_closing(bool force) override; virtual int on_scanner_closing(bool force) override;
virtual void thread_handle_usb_read(void) override; virtual void thread_handle_usb_read(void) override;
virtual void image_process(std::shared_ptr<std::vector<char>>& buff) override; virtual void image_process(std::shared_ptr<tiny_buffer>& buff) override;
virtual int on_color_mode_changed(int& color_mode); // COLOR_MODE_xxx virtual int on_color_mode_changed(int& color_mode); // COLOR_MODE_xxx
@ -55,7 +55,7 @@ private:
int readusb(USBCB &usb); int readusb(USBCB &usb);
int pop_image(void); int pop_image(void);
int get_scanner_status(USBCB &usb); int get_scanner_status(USBCB &usb);
int get_img_data(std::shared_ptr<std::vector<char>> &imagedata); int get_img_data(std::shared_ptr<tiny_buffer> &imagedata);
int writedown_device_configuration(bool type =false,HGSCANCONF_G400 *d = NULL); int writedown_device_configuration(bool type =false,HGSCANCONF_G400 *d = NULL);
void writedown_image_configuration(void); void writedown_image_configuration(void);
void printf_devconfig(HGSCANCONF_G400 *d = NULL); void printf_devconfig(HGSCANCONF_G400 *d = NULL);

View File

@ -319,7 +319,7 @@ void hg_scanner_400::thread_handle_usb_read(void)
if (ret == SCANNER_ERR_OK && usb.u32_Count > 0) if (ret == SCANNER_ERR_OK && usb.u32_Count > 0)
{ {
int totalNum = usb.u32_Count; int totalNum = usb.u32_Count;
std::shared_ptr<std::vector<char >> imagedata(aquire_memory(totalNum)); std::shared_ptr<tiny_buffer> imagedata(aquire_memory(totalNum));
if (!imagedata.get()) if (!imagedata.get())
{ {
@ -424,7 +424,7 @@ int hg_scanner_400::stop(void)
VLOG_MINI_1(LOG_LEVEL_WARNING, "stop device:(%s)\n", hg_scanner_err_name(status_)); VLOG_MINI_1(LOG_LEVEL_WARNING, "stop device:(%s)\n", hg_scanner_err_name(status_));
} }
notify_ui_working_status("取消扫描", SANE_EVENT_STATUS, status_); notify_ui_working_status("取消扫描", SANE_EVENT_STATUS, status_);
final_imgs_.Clear(); final_imgs_.clear();
return status_; return status_;
} }
@ -489,7 +489,7 @@ int hg_scanner_400::get_scanner_status(USBCB &usb)
scanner_err code = settingsdsp_400::device_status_to_hg_err(usb.u32_Data); scanner_err code = settingsdsp_400::device_status_to_hg_err(usb.u32_Data);
return code ; return code ;
} }
int hg_scanner_400::get_img_data(std::shared_ptr<std::vector<char>> &imagedata) int hg_scanner_400::get_img_data(std::shared_ptr<tiny_buffer> &imagedata)
{ {
int total = imagedata->size(), int total = imagedata->size(),
ret = SCANNER_ERR_OK, ret = SCANNER_ERR_OK,
@ -533,7 +533,7 @@ int hg_scanner_400::get_img_data(std::shared_ptr<std::vector<char>> &imagedata)
return ret; return ret;
} }
void hg_scanner_400::image_process(std::shared_ptr<std::vector<char>>& buffer) void hg_scanner_400::image_process(std::shared_ptr<tiny_buffer>& buffer)
{ {
int ret = SCANNER_ERR_OK; int ret = SCANNER_ERR_OK;
hg_imgproc::IMGPRCPARAM param; hg_imgproc::IMGPRCPARAM param;

View File

@ -25,7 +25,7 @@ class hg_scanner_400 : public hg_scanner
protected: protected:
virtual int on_scanner_closing(bool force) override; virtual int on_scanner_closing(bool force) override;
virtual void thread_handle_usb_read(void) override; virtual void thread_handle_usb_read(void) override;
virtual void image_process(std::shared_ptr<std::vector<char>>& buff) override; virtual void image_process(std::shared_ptr<tiny_buffer>& buff) override;
virtual int on_color_mode_changed(int& color_mode); // COLOR_MODE_xxx virtual int on_color_mode_changed(int& color_mode); // COLOR_MODE_xxx
@ -54,7 +54,7 @@ private:
int readusb(USBCB &usb); int readusb(USBCB &usb);
int pop_image(void); int pop_image(void);
int get_scanner_status(USBCB &usb); int get_scanner_status(USBCB &usb);
int get_img_data(std::shared_ptr<std::vector<char>> &imagedata); int get_img_data(std::shared_ptr<tiny_buffer> &imagedata);
int writedown_device_configuration(bool type =false,HGSCANCONF_G400 *d = NULL); int writedown_device_configuration(bool type =false,HGSCANCONF_G400 *d = NULL);
void writedown_image_configuration(void); void writedown_image_configuration(void);
void printf_devconfig(HGSCANCONF_G400 *d = NULL); void printf_devconfig(HGSCANCONF_G400 *d = NULL);

View File

@ -27,6 +27,7 @@ extern "C"
#include "ocr/hanwangOCRdetect.h" #include "ocr/hanwangOCRdetect.h"
} }
#endif #endif
#include "hg_ipc.h"
using namespace std; using namespace std;
#define GET_BYTE(a) ((a) & 0x0ff) #define GET_BYTE(a) ((a) & 0x0ff)
@ -84,9 +85,11 @@ namespace hg_imgproc
// load data // load data
public: public:
int load_raw_data(std::shared_ptr<std::vector<char>> buff) int load_raw_data(std::shared_ptr<tiny_buffer> buff)
{ {
buffer_.reset(new std::vector<char >(*buff)); buffer_.reset(new std::vector<char>(buff->size()));
if (buffer_.get())
memcpy(buffer_->data(), buff->data(), buff->size());
mats_.clear(); mats_.clear();
return SCANNER_ERR_OK; return SCANNER_ERR_OK;
} }
@ -843,7 +846,7 @@ namespace hg_imgproc
return (HIMGPRC)obj; return (HIMGPRC)obj;
} }
int load_buffer(HIMGPRC himg, std::shared_ptr<std::vector<char>> buff) int load_buffer(HIMGPRC himg, std::shared_ptr<tiny_buffer> buff)
{ {
return ((imgproc*)himg)->load_raw_data(buff); return ((imgproc*)himg)->load_raw_data(buff);
} }

View File

@ -8,7 +8,8 @@
#include "common_setting.h" #include "common_setting.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
//#include "common_setting.h"
class tiny_buffer;
namespace hg_imgproc namespace hg_imgproc
{ {
typedef struct _img_data typedef struct _img_data
@ -159,7 +160,7 @@ namespace hg_imgproc
HIMGPRC init(LPSCANCONF parameter,LPIMGPRCPARAM param,int pid); HIMGPRC init(LPSCANCONF parameter,LPIMGPRCPARAM param,int pid);
int load_buffer(HIMGPRC himg,std::shared_ptr<std::vector<char>> buff); int load_buffer(HIMGPRC himg,std::shared_ptr<tiny_buffer> buff);
int load_file(HIMGPRC himg, const char* path_file); int load_file(HIMGPRC himg, const char* path_file);
//图像数据转换 //图像数据转换

View File

@ -652,28 +652,32 @@ bool usb_io::claim_interterface(usb_manager::USBSIMPLEX* spl)
return true; return true;
} }
VLOG_MINI_2(LOG_LEVEL_FATAL, " first libusb_claim_interface(%d) = %s\n", spl->iface, libusb_error_name(ret)); VLOG_MINI_2(LOG_LEVEL_FATAL, "libusb_claim_interface(%d) = %s, now try some actions ...\n", spl->iface, libusb_error_name(ret));
ret = libusb_kernel_driver_active(handle_, spl->iface); ret = libusb_kernel_driver_active(handle_, spl->iface);
if (ret == 1) if (ret == 1)
{ {
ret = libusb_detach_kernel_driver(handle_, spl->iface); ret = libusb_detach_kernel_driver(handle_, spl->iface);
VLOG_MINI_2(LOG_LEVEL_FATAL, " libusb_detach_kernel_driver(%d) = %s\n", spl->iface, libusb_error_name(ret)); VLOG_MINI_2(LOG_LEVEL_FATAL, " libusb_detach_kernel_driver(%d) = %s\n", spl->iface, libusb_error_name(ret));
} }
else if (ret == LIBUSB_ERROR_NO_DEVICE) else if (ret == LIBUSB_ERROR_NO_DEVICE)
{ {
last_err_ = SCANNER_ERR_DEVICE_NOT_FOUND; last_err_ = SCANNER_ERR_DEVICE_NOT_FOUND;
VLOG_MINI_1(LOG_LEVEL_FATAL, "device(%s) maybe left when libusb_kernel_driver_active.\n", hg_log::format_ptr(dev_info_.device).c_str()); VLOG_MINI_1(LOG_LEVEL_FATAL, " device(%s) maybe left when libusb_kernel_driver_active.\n", hg_log::format_ptr(dev_info_.device).c_str());
return false; return false;
} }
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, " libusb_clear_halt(%x) ...\n", spl->port); else
libusb_clear_halt(handle_, spl->port); {
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, " libusb_release_interface(%u) ...\n", spl->iface); VLOG_MINI_2(LOG_LEVEL_FATAL, " libusb_kernel_driver_active(%d) = %d\n", spl->iface, ret);
libusb_release_interface(handle_, spl->iface); }
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, " libusb_set_configuration(%u) ...\n", spl->iconf); ret = libusb_clear_halt(handle_, spl->port);
libusb_set_configuration(handle_, spl->iconf); VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, " libusb_clear_halt(%x) = %s\n", spl->port, libusb_error_name(ret));
ret = libusb_release_interface(handle_, spl->iface);
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, " libusb_release_interface(%u) = %s\n", spl->iface, libusb_error_name(ret));
ret = libusb_set_configuration(handle_, spl->iconf);
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, " libusb_set_configuration(%u) = %s\n", spl->iconf, libusb_error_name(ret));
//ret = libusb_reset_device(handle_); //ret = libusb_reset_device(handle_);
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, " libusb_reset_device = %s\n", libusb_error_name(ret)); //VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, " libusb_reset_device = %s\n", libusb_error_name(ret));
//if (ret == LIBUSB_ERROR_NOT_FOUND) //if (ret == LIBUSB_ERROR_NOT_FOUND)
@ -689,6 +693,7 @@ bool usb_io::claim_interterface(usb_manager::USBSIMPLEX* spl)
if (ret == LIBUSB_SUCCESS) if (ret == LIBUSB_SUCCESS)
{ {
spl->claimed = true; spl->claimed = true;
VLOG_MINI_2(LOG_LEVEL_FATAL, "second libusb_claim_interface(%d) = %s\n", spl->iface, libusb_error_name(ret));
return true; return true;
} }

View File

@ -34,6 +34,9 @@
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(long) - 1) & ~(sizeof(long) - 1)) #define _INTSIZEOF(n) ((sizeof(n) + sizeof(long) - 1) & ~(sizeof(long) - 1))
#endif #endif
extern std::string g_scanner_path; // Ending with '\\'
class log_cls class log_cls
{ {
typedef void(*log_to)(const char*, void*); typedef void(*log_to)(const char*, void*);
@ -75,6 +78,7 @@ protected:
} }
public: public:
static std::string g_time_tag;
static log_cls* instance(void) static log_cls* instance(void)
{ {
if (!log_cls::inst_) if (!log_cls::inst_)
@ -112,6 +116,9 @@ public:
{ {
unsigned char bom[] = { 0x0ef, 0x0bb, 0x0bf }; unsigned char bom[] = { 0x0ef, 0x0bb, 0x0bf };
fwrite(bom, sizeof(bom), 1, file_); fwrite(bom, sizeof(bom), 1, file_);
std::string now(g_time_tag + hg_log::current_time() + g_time_tag + " started.\n");
fwrite(now.c_str(), 1, now.length(), file_);
ret = 0; ret = 0;
} }
} }
@ -141,6 +148,7 @@ public:
} }
}; };
log_cls* log_cls::inst_ = NULL; log_cls* log_cls::inst_ = NULL;
std::string log_cls::g_time_tag = "=====";
#ifdef EXPORT_AS_C #ifdef EXPORT_AS_C
extern "C" extern "C"
@ -433,10 +441,13 @@ extern "C"
return ff.found; return ff.found;
} }
std::string get_scanner_path(void)
{
return g_scanner_path;
}
static int get_log_config(const std::string& self_path, hg_log_type* type, std::string* path) static int get_log_config(const std::string& self_path, hg_log_type* type, std::string* path)
{ {
std::string me(self_path + "/configs/scanner.conf"); std::string me(self_path + PATH_SEPARATOR + "configs" + PATH_SEPARATOR + " scanner.conf");
int lv = LOG_LEVEL_ALL; int lv = LOG_LEVEL_ALL;
hg_log_type tp = LOG_TYPE_FILE; hg_log_type tp = LOG_TYPE_FILE;
@ -473,35 +484,39 @@ extern "C"
int init(void) int init(void)
{ {
char* file = nullptr; char* file = nullptr;
std::string me(g_module_path), path(""); std::string path("");
hg_log_type type = LOG_TYPE_FILE; hg_log_type type = LOG_TYPE_FILE;
int level = get_log_config(me, &type, &path); int level = get_log_config(get_scanner_path(), &type, &path);
if (type == LOG_TYPE_FILE) if (type == LOG_TYPE_FILE)
{ {
if (path.empty()) std::string name(""),
path = me; paths[] = {pe_path(&name), get_scanner_path(), simple_ini::temporary_path()};
path += "/log"; int ind = 0;
if (!create_folder(path.c_str()))
if (path.empty() || !create_folder(path.c_str()))
path = paths[ind++];
else
ind = sizeof(paths) / sizeof(paths[0]) + 2;
for (; ind < sizeof(paths) / sizeof(paths[0]); ++ind)
{ {
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Create log-folder '%s' failed(%d), now try temporary directory\n", path.c_str(), errno); path = paths[ind] + PATH_SEPARATOR + "log";
path = simple_ini::temporary_path() + "/log"; if (create_folder(path.c_str()))
if (!create_folder(path.c_str())) break;
{ }
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "create temporary directory '%s' failed(%d), log to console\n", path.c_str(), errno); if(ind == sizeof(paths) / sizeof(paths[0]))
type = LOG_TYPE_CONSOLE; {
} VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Try PE, scanner and temporary path failed(%d), log to console\n", errno);
type = LOG_TYPE_CONSOLE;
} }
if (type == LOG_TYPE_FILE) if (type == LOG_TYPE_FILE)
{ {
std::string name("");
pe_path(&name);
if (name.empty()) if (name.empty())
path += "/scanner.log"; path += std::string(PATH_SEPARATOR) + "scanner.log";
else else
path += "/" + name + ".log"; path += PATH_SEPARATOR + name + ".log";
file = &path[0]; file = &path[0];
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Log to file: '%s'\n", path.c_str()); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Log to file: '%s'\n", path.c_str());
} }
@ -510,6 +525,11 @@ extern "C"
return log_cls::instance()->set_log_type(type, file); return log_cls::instance()->set_log_type(type, file);
} }
void unint(void)
{
std::string now(log_cls::g_time_tag + hg_log::current_time() + log_cls::g_time_tag + " exited.\n");
log(now.c_str());
}
void log(int level, const char* info) void log(int level, const char* info)
{ {
if (lcb_) if (lcb_)

View File

@ -10,6 +10,9 @@
#ifdef WIN32 #ifdef WIN32
#define bzero(a, l) memset(a, 0, l) #define bzero(a, l) memset(a, 0, l)
#define PATH_SEPARATOR "\\"
#else
#define PATH_SEPARATOR "/"
#endif #endif
#ifdef OEM_HANWANG #ifdef OEM_HANWANG
@ -43,6 +46,7 @@ extern "C"
std::string u2utf8(const wchar_t* u); std::string u2utf8(const wchar_t* u);
std::string pe_path(std::string* name = nullptr); std::string pe_path(std::string* name = nullptr);
std::string get_module_full_path(const char* module_part_name); std::string get_module_full_path(const char* module_part_name);
std::string get_scanner_path(void);
unsigned long long available_memory(void); unsigned long long available_memory(void);
void str_tolower(std::string& str); void str_tolower(std::string& str);
bool create_folder(const char* fodler); bool create_folder(const char* fodler);
@ -54,6 +58,7 @@ extern "C"
// //
// Return: 0 - success, or -1 in LOG_TYPE_FILE and log_file cannot be created // Return: 0 - success, or -1 in LOG_TYPE_FILE and log_file cannot be created
int init(void); int init(void);
void unint(void);
void log(int level, const char* info); void log(int level, const char* info);
bool is_log_level_enabled(int level); bool is_log_level_enabled(int level);

View File

@ -3,6 +3,12 @@
#include "../hgdev/scanner_manager.h" #include "../hgdev/scanner_manager.h"
#include <iostream> #include <iostream>
#ifdef WIN32
#include <fileapi.h>
#else
#include <sys/vfs.h>
#include <string.h>
#endif
#ifndef VERSION_MAJOR #ifndef VERSION_MAJOR
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
@ -16,8 +22,9 @@
| (((unsigned long long)(b) & 0x0ffff) << 32) \ | (((unsigned long long)(b) & 0x0ffff) << 32) \
| (((unsigned long long)(c) & 0x0ffff) << 16) \ | (((unsigned long long)(c) & 0x0ffff) << 16) \
| (((unsigned long long)(d) & 0x0ffff) << 0)) | (((unsigned long long)(d) & 0x0ffff) << 0))
#define GET_BUILD_VER VERSION_BUILD - 100000
std::string g_module_path = ""; std::string g_scanner_path = "";
static std::string g_sane_name = ""; static std::string g_sane_name = "";
static std::string g_sane_ver = ""; static std::string g_sane_ver = "";
@ -25,16 +32,30 @@ extern "C"
{ {
scanner_err hg_scanner_initialize(sane_callback callback, void* reserve) scanner_err hg_scanner_initialize(sane_callback callback, void* reserve)
{ {
#ifndef WIN32 std::string name(""),
size_t pos = 0; pe(hg_log::pe_path(&name)),
g_module_path = hg_log::get_module_full_path((std::string(GET_BACKEND_NAME) + ".so").c_str()); path("\\"),
pos = g_module_path.rfind('/'); scanner(g_scanner_path),
sane(hg_log::get_module_full_path((g_sane_name + ".so").c_str()));
#ifdef WIN32
size_t pos = g_scanner_path.rfind('\\');
if (pos++ != std::string::npos) if (pos++ != std::string::npos)
g_module_path.erase(pos); g_scanner_path.erase(pos);
#else
size_t pos = 0;
g_scanner_path = hg_log::get_module_full_path((std::string(GET_BACKEND_NAME) + ".so").c_str());
scanner = g_scanner_path;
path = "/";
pos = g_scanner_path.rfind('/');
if (pos++ != std::string::npos)
g_scanner_path.erase(pos);
#endif #endif
hg_log::init(); hg_log::init();
VLOG_MINI_5(LOG_LEVEL_DEBUG_INFO, "Module device: [%u.%u.%u.%u] - %s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_YEAR, GET_BUILD_VER, scanner.c_str());
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Module sane : [%s] - %s\n", g_sane_ver.c_str(), sane.c_str());
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Module exe : %s\n", (pe + path + name).c_str());
hg_scanner_mgr::set_version(VERSION_MAJOR, VERSION_MINOR, VERSION_YEAR, VERSION_BUILD - 100000); hg_scanner_mgr::set_version(VERSION_MAJOR, VERSION_MINOR, VERSION_YEAR, GET_BUILD_VER);
hg_scanner_mgr::instance(callback); hg_scanner_mgr::instance(callback);
return SCANNER_ERR_OK; return SCANNER_ERR_OK;
@ -42,11 +63,12 @@ extern "C"
void hg_scanner_uninitialize(void) void hg_scanner_uninitialize(void)
{ {
hg_scanner_mgr::clear(); hg_scanner_mgr::clear();
hg_log::unint();
} }
unsigned long long hg_scanner_get_version(void) unsigned long long hg_scanner_get_version(void)
{ {
return MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_YEAR, VERSION_BUILD - 100000); return MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_YEAR, GET_BUILD_VER);
} }
scanner_err hg_scanner_enum(ScannerInfo* scanner_list, long* count, bool local_only) scanner_err hg_scanner_enum(ScannerInfo* scanner_list, long* count, bool local_only)
@ -256,6 +278,54 @@ extern "C"
return buf; return buf;
} }
int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block)
{
int ret = SCANNER_ERR_OK;
#ifdef WIN32
ULARGE_INTEGER av = { 0 },
all = { 0 };
if (GetDiskFreeSpaceExA(path, &av, &all, NULL))
{
if (total)
*total = all.QuadPart;
if (avail)
*avail = av.QuadPart;
if (block)
{
DWORD sec = 0,
clu = 0;
std::string root(path);
size_t pos = root.find(":\\");
if (pos != std::string::npos)
root.erase(pos + 2);
if (GetDiskFreeSpaceA(root.c_str(), &clu, &sec, NULL, NULL))
{
*block = clu * sec;
}
}
}
else
ret = GetLastError();
#else
struct statfs fs = { 0 };
ret = statfs(path, &fs);
if (ret == 0)
{
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, " Total: %lld, Free: %lld, Avail: %lld, block size: %lld\n",
fs.f_blocks, fs.f_bfree, fs.f_bavail, fs.f_bsize);
if (total)
*total = fs.f_blocks * fs.f_bsize;
if (avail)
*avail = fs.f_bavail * fs.f_bsize;
if (block)
*block = fs.f_bsize;
}
#endif
return ret;
}
} }
@ -265,15 +335,15 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{ {
if (reason == DLL_PROCESS_ATTACH) if (reason == DLL_PROCESS_ATTACH)
{ {
if (g_module_path.empty()) if (g_scanner_path.empty())
{ {
char path[MAX_PATH] = { 0 }; char path[MAX_PATH] = { 0 };
GetModuleFileNameA(inst, path, _countof(path) - 1); GetModuleFileNameA(inst, path, _countof(path) - 1);
if (strrchr(path, '\\')) // if (strrchr(path, '\\'))
{ {
strrchr(path, '\\')[1] = 0; // strrchr(path, '\\')[1] = 0;
g_module_path = path; g_scanner_path = path;
} }
} }
} }

View File

@ -33,6 +33,8 @@
#define iconv_t void* #define iconv_t void*
#endif #endif
static std::string g_sane_path = "";
namespace local_utility namespace local_utility
{ {
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -275,12 +277,6 @@ namespace local_utility
{ {
if (version_code) if (version_code)
*version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, VERSION_BUILD); // leading-char '1' is used for avoid compiler considering '0118' as an octal number :) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, VERSION_BUILD); // leading-char '1' is used for avoid compiler considering '0118' as an octal number :)
unsigned long long v = hg_scanner_get_version();
unsigned short* w = (unsigned short*)&v;
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "scanner version: %u.%u.%u.%u\n", w[3], w[2], w[1], w[0]);
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "%s version: %u.%u.%u\n", GET_BACKEND_NAME, SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, VERSION_BUILD);
} }
void stop_work(void) void stop_work(void)
{ {
@ -310,10 +306,10 @@ hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), std_opt_(nullptr
char path[512] = { 0 }; char path[512] = { 0 };
size_t pos = 0; size_t pos = 0;
g_module_path = get_file_path((std::string(GET_BACKEND_NAME) + ".so").c_str(), path); g_sane_path = get_file_path((std::string(GET_BACKEND_NAME) + ".so").c_str(), path);
pos = g_module_path.rfind('/'); pos = g_sane_path.rfind('/');
if (pos++ != std::string::npos) if (pos++ != std::string::npos)
g_module_path.erase(pos); g_sane_path.erase(pos);
#endif #endif
} }
hg_sane_middleware::~hg_sane_middleware() hg_sane_middleware::~hg_sane_middleware()
@ -1962,13 +1958,11 @@ extern "C" { // avoid compiler exporting name in C++ style !!!
#ifdef WIN32 #ifdef WIN32
std::string g_module_path = "";
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{ {
if (reason == DLL_PROCESS_ATTACH) if (reason == DLL_PROCESS_ATTACH)
{ {
if (g_module_path.empty()) if (g_sane_path.empty())
{ {
char path[MAX_PATH] = { 0 }; char path[MAX_PATH] = { 0 };
@ -1976,7 +1970,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
if (strrchr(path, '\\')) if (strrchr(path, '\\'))
{ {
strrchr(path, '\\')[1] = 0; strrchr(path, '\\')[1] = 0;
g_module_path = path; g_sane_path = path;
} }
} }
} }

View File

@ -131,8 +131,6 @@
#define MAKE_STR(str) _TO_STR(str) #define MAKE_STR(str) _TO_STR(str)
#define GET_BACKEND_NAME MAKE_STR(BACKEND_NAME) #define GET_BACKEND_NAME MAKE_STR(BACKEND_NAME)
#include <string>
extern std::string g_module_path; // Ending with '\\'
typedef struct _device typedef struct _device
{ {
@ -433,6 +431,19 @@ extern "C"{
// Return: 返回buf // Return: 返回buf
char* get_file_path(const char* name, char* buf); char* get_file_path(const char* name, char* buf);
// Function: 获取磁盘空间
//
// Parameters: path - 全路径
//
// total - 总空间大小(字节)
//
// avail - 可用空间大小(字节)
//
// block - 磁盘单元(块/簇)大小(字节)
//
// Return: 0 - 成功;其它为失败代码
int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif