datatypes: raw text items with minimal conversion (FDO #52791)

When using "raw/text/calendar" or "raw/text/vcard" as SyncEvolution
"databaseFormat", all parsing and conversion is skipped. The backend's
data is identical to the item data in the engine. Finding duplicates
in a slow sync is very limited when using these types because the entire
item data must match exactly.

This is useful for the file backend when the goal is to store an exact copy
of what a peer has or for limited, read-only backends (PBAP).

The implementation uses the "raw" base type which does nothing but storing
the item content verbatim. That type requires a field named "ITEMDATA". After
renaming the variable used by our MAKETEXTWITHPROFILE/PARSETEXTWITHPROFILE
with other, more complex types, all we have to do is skip this conversion
by not providing a profile name.
In a refresh-from-remote local sync of 1000 contacts with photo data
using the file backend, this reduces the number of CPU cycles from
2861476184 to 1840952543 on the server side.
This commit is contained in:
Patrick Ohly 2014-09-09 22:19:43 +02:00
parent f994f1efb2
commit 626e027d3d
4 changed files with 37 additions and 5 deletions

View File

@ -1327,7 +1327,7 @@ sysync::TSyError PbapSyncSource::readItemAsKey(sysync::cItemID aID, sysync::KeyH
}
pcrecpp::StringPiece vcard;
if (m_pullAll->getContact(aID->item, vcard)) {
return getSynthesisAPI()->setValue(aItemKey, "data", vcard.data(), vcard.size());
return getSynthesisAPI()->setValue(aItemKey, "itemdata", vcard.data(), vcard.size());
} else {
return sysync::DB_NotFound;
}

View File

@ -165,7 +165,7 @@ void SyncSourceBase::getDatastoreXML(string &xml, XMLConfigFragments &fragments)
}
xmlstream <<
" ]]></afterreadscript>\n"
" <map name='data' references='itemdata' type='string'/>\n";
" <map name='itemdata' references='itemdata' type='string'/>\n";
}
xmlstream <<
" <automap/>\n"
@ -776,6 +776,16 @@ void SyncSourceSerialize::getSynthesisInfo(SynthesisInfo &info,
} else if (type == "text/plain") {
info.m_fieldlist = "Note";
info.m_profile = "\"Note\", 2";
} else if (type == "raw/text/vcard") {
info.m_native = "vCard30";
info.m_fieldlist = "Raw";
info.m_datatypes =
" <use datatype='raw-vcard' mode='rw' preferred='yes'/>\n";
} else if (type == "raw/text/calendar") {
info.m_native = "iCalendar20";
info.m_fieldlist = "Raw";
info.m_datatypes =
" <use datatype='raw-calendar' mode='rw' preferred='yes'/>\n";
} else {
throwError(SE_HERE, string("default MIME type not supported: ") + type);
}
@ -831,6 +841,12 @@ std::string SyncSourceBase::getDataTypeSupport(const std::string &type,
datatypes =
" <use datatype='note10' mode='rw' preferred='yes'/>\n"
" <use datatype='note11' mode='rw'/>\n";
} else if (type == "raw/text/vcard") {
datatypes =
" <use datatype='raw-vcard' mode='rw' preferred='yes'/>\n";
} else if (type == "raw/text/calendar") {
datatypes =
" <use datatype='raw-calendar' mode='rw' preferred='yes'/>\n";
} else if (type.empty()) {
throwError(SE_HERE, "no MIME type configured");
} else {
@ -845,14 +861,14 @@ sysync::TSyError SyncSourceSerialize::readItemAsKey(sysync::cItemID aID, sysync:
std::string item;
readItem(aID->item, item);
TSyError res = getSynthesisAPI()->setValue(aItemKey, "data", item.c_str(), item.size());
TSyError res = getSynthesisAPI()->setValue(aItemKey, "itemdata", item.c_str(), item.size());
return res;
}
SyncSource::Operations::InsertItemAsKeyResult_t SyncSourceSerialize::insertItemAsKey(sysync::KeyH aItemKey, sysync::ItemID newID)
{
SharedBuffer data;
TSyError res = getSynthesisAPI()->getValue(aItemKey, "data", data);
TSyError res = getSynthesisAPI()->getValue(aItemKey, "itemdata", data);
if (!res) {
InsertItemResult inserted = insertItem("", data.get());
@ -882,7 +898,7 @@ SyncSource::Operations::InsertItemAsKeyResult_t SyncSourceSerialize::insertItemA
SyncSource::Operations::UpdateItemAsKeyResult_t SyncSourceSerialize::updateItemAsKey(sysync::KeyH aItemKey, sysync::cItemID aID, sysync::ItemID newID)
{
SharedBuffer data;
TSyError res = getSynthesisAPI()->getValue(aItemKey, "data", data);
TSyError res = getSynthesisAPI()->getValue(aItemKey, "itemdata", data);
if (!res) {
InsertItemResult inserted = insertItem(aID->item, data.get());

View File

@ -0,0 +1,5 @@
<!-- list of internal fields representing plain text note data -->
<fieldlist name="Raw">
<field name="ITEMDATA" type="string" compare="always"/>
</fieldlist>

View File

@ -0,0 +1,11 @@
<datatype name="raw-vcard" basetype="raw">
<use fieldlist="Raw"/>
<typestring>text/vcard</typestring>
<versionstring>3.0</versionstring>
</datatype>
<datatype name="raw-calendar" basetype="raw">
<use fieldlist="Raw"/>
<typestring>text/calendar</typestring>
<versionstring>2.0</versionstring>
</datatype>