void session::deserialize(string& buf, std::map<string, VBUF*>& attrs) { attrs_clear(attrs); // 先重置 session 前一次查询状态 ACL_ARGV* tokens = acl_argv_split(buf.c_str(), "\t"); ACL_ITER iter; acl_foreach(iter, tokens) { char* ptr = (char*) iter.data; // 重复使用原来的内存区,因为 tokens 中已经存储了中间结果数据 buf.clear(); if (unescape(ptr, strlen(ptr), buf) == false) { logger_error("unescape error"); continue; } ptr = buf.c_str(); // 因为 acl::string 肯定能保证缓冲区数据的尾部有 \0,所以在用 // strchr 时不必须担心越界问题,但 std::string 并不保证这样 char* p1 = strchr(ptr, 1); if (p1 == NULL || *(p1 + 1) == 0) continue; *p1++ = 0; std::map<string, VBUF*>::iterator it = attrs.find(ptr); // xxx: 以防有重复的属性 if (it != attrs.end()) vbuf_free(it->second); // 将从后端取得数据属性都设为 TODO_SET attrs[ptr] = vbuf_new(p1, buf.length() - (p1 - buf.c_str()), TODO_SET); }
void session::attrs_clear(std::map<string, VBUF*>& attrs) { if (attrs.empty()) return; std::map<string, VBUF*>::iterator it = attrs.begin(); for (; it != attrs.end(); ++it) vbuf_free(it->second); attrs.clear(); }
bool session::del(const char* name, bool delay /* = false */) { if (delay) { std::map<string, VBUF*>::iterator it = attrs_cache_.find(name); if (it == attrs_cache_.end()) attrs_cache_[name] = vbuf_new("", 0, TODO_DEL); else it->second->todo = TODO_DEL; dirty_ = true; return true; } // 直接操作后端 cache 服务器,删除属性字段 string buf(256); if (get_data(sid_->buf, buf) == false) return true; deserialize(buf, attrs_); std::map<string, VBUF*>::iterator it = attrs_.find(name); if (it == attrs_.end()) return false; // 先删除并释放对应的对象 vbuf_free(it->second); attrs_.erase(it); // 如果 sid 中已经没有了数据,则应该将 sid 对象从 memcached 中删除 if (attrs_.empty()) { // 调用虚函数,删除该 sid 对应的缓存内容 if (del_data(sid_->buf) == false) { logger_error("del sid(%s) error", sid_->buf); return false; } return true; } // 向 memcached 中重新添加剩余的数据 serialize(attrs_, buf); attrs_clear(attrs_); if (set_data(sid_->buf, buf.c_str(), buf.length(), ttl_) == false) { logger_error("set cache error, sid(%s)", sid_->buf); return false; } return true; }
void storageTask( void *param ) { int ret; storageMsg_t msgData; storageMsg_t *msg = &msgData; unsigned int msg_prio; //int is_finish =0; printf("\nStorage thread enter ...\n\n"); while (1) { ret = mq_receive(storageMsgQ, (char *) msg, sizeof(storageMsg_t), &msg_prio); if (ret < 0) { printf("[%s:%d], storage receive msg fail.\n", __FUNCTION__, __LINE__); continue; } //printf("receive storage msg %d, 0x%x\n", msg->cmd, msg->handle); if(msg->cmd == STORAGE_CMD_WRITE || msg->cmd == STORAGE_CMD_WRITE_AUDIO) { streamInfo_t *streamHandle = (streamInfo_t *) msg->handle; storageHandle_t *storageHandle = (storageHandle_t*) streamHandle->storageHandle; gpMuxPkt_t MuxPkt; int isAudio = (msg->cmd == STORAGE_CMD_WRITE_AUDIO) ? 1: 0; if (storageHandle && storageHandle->hdMux) { ret = 0; if (isAudio) { MuxPkt.data = (UINT8*)((audio_buffer_t*)(msg->buffer))->frame->pAddr; MuxPkt.size = msg->nBytes; MuxPkt.pts = msg->pts;//AUDIO_BUFFER_TIME; //printf("audio time =%d\n",msg->pts); if(storageHandle->hdMux) ret = g_save_Mux->pack(storageHandle->hdMux, &MuxPkt, GP_ES_TYPE_AUDIO); abuf_free((audio_buffer_t*)(msg->buffer)); } else { IPC_Video_Frame_s* frame = ((video_buffer_t*)(msg->buffer))->frame; if (frame->thumb && storageHandle->hdMux) { MuxPkt.data = frame->thumb; MuxPkt.size = frame->thumb_size; ret = g_save_Mux->pack(storageHandle->hdMux, &MuxPkt, GP_ES_TYPE_THUMB); } MuxPkt.data = frame->pFrameAddr; MuxPkt.size = msg->nBytes; if (!storageHandle->time_lapse && (storageHandle->last_pts > 0) && (msg->pts > storageHandle->last_pts)) MuxPkt.pts = msg->pts - storageHandle->last_pts; else MuxPkt.pts = 1000/storageHandle->framerate; if (MuxPkt.pts > 3600*1000) //avoid unexpected frame time { printf("unexpected large frame time %u\n", MuxPkt.pts); MuxPkt.pts = 1000/storageHandle->framerate; } storageHandle->last_pts = msg->pts; MuxPkt.frameType = msg->frameType; if(storageHandle->hdMux) ret = g_save_Mux->pack(storageHandle->hdMux, &MuxPkt, GP_ES_TYPE_VIDEO); vbuf_free((video_buffer_t*)(msg->buffer)); } if (ret != 0) { if (ret == MUX_MEM_FULL) { printf("[dvr] disk is full, stop recording.\n"); streamHandle->status = STATUS_DISK_FULL; } else if (ret == MUX_FILE_SIZE_REACH) { printf("[dvr] reach maximum file size (2G), stop recording.\n"); streamHandle->status = STATUS_FILE_SIZE_LIMIT; } else { printf("[dvr] unknown file error. stop recording.\n"); streamHandle->status = STATUS_DISK_ERROR; } g_save_Mux->close(storageHandle->hdMux); storageHandle->hdMux = 0; if(storageHandle->file) fclose(storageHandle->file); free(storageHandle); streamHandle->storageHandle = NULL; sync(); } } else { if (isAudio) abuf_free((audio_buffer_t*)(msg->buffer)); else vbuf_free((video_buffer_t*)(msg->buffer)); } } else if (msg->cmd == STORAGE_CMD_LOCK) { streamInfo_t *streamHandle = (streamInfo_t *) msg->handle; storageHandle_t *storageHandle = (storageHandle_t*) streamHandle->storageHandle; if(storageHandle->hdMux) g_save_Mux->set(storageHandle->hdMux, MUX_LOCK_FILE, 0); } else if (msg->cmd == STORAGE_CMD_FINISH) { streamInfo_t *streamHandle = (streamInfo_t *) msg->handle; storageHandle_t *storageHandle = (storageHandle_t*) streamHandle->storageHandle; //is_finish =1; if (storageHandle){ if (storageHandle->hdMux) { g_save_Mux->close(storageHandle->hdMux); storageHandle->hdMux = 0; } if(storageHandle->file) fclose(storageHandle->file); free(storageHandle); streamHandle->storageHandle = NULL; sync(); } } else if (msg->cmd == STORAGE_CMD_CLOSE) { mq_close(storageMsgQ); break; } } printf("\nStorage thread exit ...\n\n"); }
session::~session() { reset(); vbuf_free(sid_); }
bool session::flush() { if (!dirty_) return true; dirty_ = false; string buf(256); // 调用纯虚接口,获得原来的 sid 数据 if (get_data(sid_->buf, buf) == true) { if (!sid_saved_) sid_saved_ = true; deserialize(buf, attrs_); // 反序列化 } std::map<string, VBUF*>::iterator it_cache = attrs_cache_.begin(); for (; it_cache != attrs_cache_.end(); ++it_cache) { // 如果该属性已存在,则需要先释放原来的属性值后再添加新值 std::map<string, VBUF*>::iterator it_attr = attrs_.find(it_cache->first); if (it_attr == attrs_.end()) { if (it_cache->second->todo == TODO_SET) attrs_[it_cache->first] = it_cache->second; else vbuf_free(it_cache->second); } else if (it_cache->second->todo == TODO_SET) { // 清除旧的数据 vbuf_free(it_attr->second); // 设置新的数据 attrs_[it_cache->first] = it_cache->second; } else if (it_cache->second->todo == TODO_DEL) { vbuf_free(it_attr->second); attrs_.erase(it_attr); vbuf_free(it_cache->second); } else { logger_warn("unknown todo(%d)", (int) it_cache->second->todo); vbuf_free(it_cache->second); } } // 清除缓存的数据:因为内部的数据已经被添加至 attrs_ 中, // 所以只需要将 attrs_cache_ 空间清除即可 attrs_cache_.clear(); serialize(attrs_, buf); // 序列化数据 attrs_clear(attrs_); // 清除属性集合数据 // 调用纯虚接口,向 memcached 或类似缓存中添加数据 if (set_data(sid_->buf, buf.c_str(), buf.length(), ttl_) == false) { logger_error("set cache error, sid(%s)", sid_->buf); return false; } if (!sid_saved_) sid_saved_ = true; return true; }