Пример #1
0
bool Writer::run()
{
    for (;;) {
        /*
         * Dequeue request, control request first
         */
        shared_ptr<IORequest> request = m_link->waitIORequest();

        /*
         * Request locked area
         */
        Mutex::Autolock l(request->locker());

        shared_ptr<Package> pkg = request->getPackage();
        PackageHeader *hdr = &pkg->header;

        if (mustStop(hdr)) {
            /*
             * Quit now if stop requested
             */
            break;
        }

        /*
         * Prepare IO transfer
         */
        char *buffer = (char *)hdr;
        int hdrSize = sizeof(struct PackageHeader);
        int dataLength = hdr->dataLength;

        int transferSize = hdrSize;

        if (dataLength &&
                hdr->type != PkgType::ACK_DATA) {
            /*
             * Combined transfer if with pay-load
             */
            buffer = const_cast<char *>(pkg->data) - hdrSize;

            memmove(buffer, hdr, hdrSize);

            transferSize += dataLength;
        }

        /*
         * Do IO transfer
         */
        bool writeOK = false;
        bool syncOK = true;

        writeOK = write(buffer, transferSize);
        if (writeOK && request->isNeedSync()) {
            /*
             * Synchronization needed, so do flush
             */
            syncOK = m_link->flush();
        }

        if (!writeOK) {
            /*
             * Dump header when error occur
             */
            Log::e(LOG_TAG, "Failed to write package: ");
            hdr->dump();
        }

        if (request->isWaitSend()) {
            /*
             * Wake up sender
             */
            request->complete(writeOK && syncOK ?
                                UniconnectErrorCode::ENOERROR :
                                UniconnectErrorCode::ELINKDISCONNECTED);
        }

        /*
         * Debug stuff
         */
        if (Log::isDebugEnabled()) {
            Log::d(string(LOG_TAG).c_str(),
                    "Data Path: Package: %s,"
                    " Data length: %d --------------> Port: %u,"
                    " Send Result: %s",
                    PackageHeader::typeToString(hdr->type),
                    hdr->dataLength,
                    hdr->port,
                    writeOK && syncOK ? "Success." : "Failed.");
        }
    }

    return false;
}
Пример #2
0
void COutputStreamSerializer::SavePackage (std::ostream *s, void *rootObj, Class *rootObjClass)
{
	PackageHeader ph;

	stream = s;
	unsigned startOffset = stream->tellp();

	stream->seekp (startOffset + sizeof (PackageHeader));
	ph.objDataOffset = (int)stream->tellp();

	// Insert the first object that will provide references to everything
	ObjectID obj;
	obj.class_ = rootObjClass;
	obj.isEmbedded = false;
	obj.id = 0;
	ptrToID[rootObj] = obj;
	pendingObjects.push_back (ptrToID.find(rootObj));
	objects.push_back (&ptrToID[rootObj]);

	// Save until all the referenced objects have been stored
	while (!pendingObjects.empty ())
	{
		vector <ObjIDmap::iterator> po = pendingObjects;
		pendingObjects.clear ();

		for (vector<ObjIDmap::iterator>::iterator i=po.begin();i!=po.end();++i)
		{
			ObjectID& obj = (*i)->second;
			obj.class_->SerializeInstance (this, (*i)->first);
		}
	}

	// Collect a set of all used classes
	map<creg::Class *,ClassRef> classMap;
	vector <ClassRef*> classRefs;
	for (ObjIDmap::iterator oi = ptrToID.begin(); oi != ptrToID.end(); ++oi) {
		//printf ("Obj: %s\n", oi->second.class_->name.c_str());
		map<creg::Class*,ClassRef>::iterator cr = classMap.find (oi->second.class_);
		if (cr == classMap.end()) {
			ClassRef *pRef = &classMap[oi->second.class_];
			pRef->index = classRefs.size();
			pRef->class_ = oi->second.class_;

			classRefs.push_back (pRef);
			oi->second.classIndex = pRef->index;
		} else 
			oi->second.classIndex = cr->second.index;
	}

	// Write the class references
	ph.numObjClassRefs = classRefs.size();
	ph.objClassRefOffset = (int)stream->tellp();
	for (uint a=0;a<classRefs.size();a++) {
		WriteZStr (*stream, classRefs[a]->class_->name);
		// write a checksum (unused atm)
		int checksum = swabdword(0);
		stream->write ((char*)&checksum, sizeof(int));
	}

	// Write object info
	ph.objTableOffset = (int)stream->tellp();
	ph.numObjects = objects.size();
	for (uint a=0;a<objects.size();a++)
	{
		ObjectID *o = objects[a];
		PackageObject d;

		d.classRefIndex = o->classIndex;
		d.isEmbedded = o->isEmbedded ? 1 : 0;

		d.SwapBytes ();
		stream->write ((char*)&d, sizeof(PackageObject));
	}

	// Calculate a checksum for metadata verification
	ph.metadataChecksum = 0;
	for (uint a=0;a<classRefs.size();a++)
	{
		Class *c = classRefs[a]->class_;
		c->CalculateChecksum (ph.metadataChecksum);
	}
	printf("Checksum: %d\n", ph.metadataChecksum);

	stream->seekp (startOffset);
	memcpy(ph.magic, CREG_PACKAGE_FILE_ID, 4);
	ph.SwapBytes ();
	stream->write ((const char *)&ph, sizeof(PackageHeader));

	objects.clear();
	ptrToID.clear();
}
Пример #3
0
void COutputStreamSerializer::SavePackage(std::ostream* s, void* rootObj, Class* rootObjClass)
{
	PackageHeader ph;

	stream = s;
	unsigned startOffset = stream->tellp();
	stream->write((char*)&ph, sizeof(PackageHeader));
	stream->seekp(startOffset + sizeof(PackageHeader));
	ph.objDataOffset = (int)stream->tellp();

	// Insert dummy object with id 0
	objects.push_back(ObjectRef(0, 0, true, 0));
	ObjectRef* obj = &objects.back();
	obj->classIndex = 0;

	// Insert the first object that will provide references to everything
	objects.push_back(ObjectRef(rootObj, objects.size(), false, rootObjClass));
	obj = &objects.back();
	ptrToId[rootObj].push_back(obj);
	pendingObjects.push_back(obj);

	// Save until all the referenced objects have been stored
	while (!pendingObjects.empty())
	{
		const std::vector<ObjectRef*> po = pendingObjects;
		pendingObjects.clear();

		for (std::vector<ObjectRef*>::const_iterator i = po.begin(); i != po.end(); ++i)
		{
			ObjectRef* obj = *i;
			SerializeObject(obj->class_, obj->ptr, obj);
			//LOG_SL(LOG_SECTION_CREG_SERIALIZER, L_DEBUG, "Serialized %s size:%i", obj->class_->name.c_str(), sz);
		}
	}

	// Collect a set of all used classes
	std::map<creg::Class*, ClassRef> classMap;
	std::vector<ClassRef*> classRefs;
	for (ObjectRef& oRef: objects) {
		if (oRef.ptr == nullptr)
			continue;

		creg::Class* c = oRef.class_;
		while (c) {
			std::map<creg::Class*, ClassRef>::iterator cr = classMap.find(c);
			if (cr == classMap.end()) {
				ClassRef* pRef = &classMap[c];
				pRef->index = classRefs.size();
				pRef->class_ = c;
				classRefs.push_back(pRef);
			}
			c = c->base();
		}

		std::map<creg::Class*, ClassRef>::iterator cr = classMap.find(oRef.class_);
		oRef.classIndex = cr->second.index;
	}


	if (LOG_IS_ENABLED(L_DEBUG)) {
		for (auto &it: classSizes) {
			LOG_L(L_DEBUG, "%30s %10u %10u",
					it.first->name.c_str(),
					classCounts[it.first],
					it.second);
		}
	}


	// Write the class references & calc their checksum
	ph.numObjClassRefs = classRefs.size();
	ph.objClassRefOffset = (int)stream->tellp();
	for (uint a = 0; a < classRefs.size(); a++) {
		creg::Class* c =  classRefs[a]->class_;
		WriteZStr(*stream, c->name);
	};

	// Write object info
	ph.objTableOffset = (int)stream->tellp();
	ph.numObjects = objects.size();
	for (ObjectRef& oRef: objects) {
		int classRefIndex = oRef.classIndex;
		char isEmbedded = oRef.isEmbedded ? 1 : 0;
		WriteVarSizeUInt(stream, classRefIndex);
		stream->write((char*)&isEmbedded, sizeof(char));

		char mgcnt = oRef.memberGroups.size();
		WriteVarSizeUInt(stream, mgcnt);

		std::vector<COutputStreamSerializer::ObjectMemberGroup>::iterator j;
		for (j = oRef.memberGroups.begin(); j != oRef.memberGroups.end(); ++j) {
			std::map<creg::Class*, ClassRef>::iterator cr = classMap.find(j->membersClass);
			if (cr == classMap.end()) throw "Cannot find member class ref";
			int cid = cr->second.index;
			WriteVarSizeUInt(stream, cid);

			unsigned int mcnt = j->members.size();
			WriteVarSizeUInt(stream, mcnt);

			bool hasSerializerMember = false;
			char groupFlags = 0;
			if (!j->members.empty() && (j->members.back().memberId == -1)) {
				groupFlags |= 0x01;
				hasSerializerMember = true;
			}
			stream->write((char*)&groupFlags, sizeof(char));

			int midx = 0;
			std::vector<COutputStreamSerializer::ObjectMember>::iterator k;
			for (k = j->members.begin(); k != j->members.end(); ++k, ++midx) {
				if ((k->memberId != midx) && (!hasSerializerMember || k != (j->members.end() - 1))) {
					throw "Invalid member id";
				}
				WriteVarSizeUInt(stream, k->size);
			}
		}
	}

	// Calculate a checksum for metadata verification
	ph.metadataChecksum = 0;
	for (uint a = 0; a < classRefs.size(); a++)
	{
		Class* c = classRefs[a]->class_;
		c->CalculateChecksum(ph.metadataChecksum);
	}

	int endOffset = stream->tellp();
	stream->seekp(startOffset);
	memcpy(ph.magic, CREG_PACKAGE_FILE_ID, 4);
	ph.SwapBytes();
	stream->write((const char*)&ph, sizeof(PackageHeader));

	LOG_SL(LOG_SECTION_CREG_SERIALIZER, L_DEBUG,
			"Checksum: %X\nNumber of objects saved: %i\nNumber of classes involved: %i",
			ph.metadataChecksum, int(objects.size()), int(classRefs.size()));

	stream->seekp(endOffset);
	ptrToId.clear();
	pendingObjects.clear();
	objects.clear();
}