File indexing completed on 2024-05-12 05:26:07
0001 /* 0002 * Copyright (C) 2016 Christian Mollekopf <mollekopf@kolabsys.com> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) version 3, or any 0008 * later version accepted by the membership of KDE e.V. (or its 0009 * successor approved by the membership of KDE e.V.), which shall 0010 * act as a proxy defined in Section 6 of version 3 of the license. 0011 * 0012 * This library is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Lesser General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Lesser General Public 0018 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 #include "synchronizerstore.h" 0021 0022 #include "index.h" 0023 #include "log.h" 0024 0025 using namespace Sink; 0026 0027 SynchronizerStore::SynchronizerStore(Sink::Storage::DataStore::Transaction &transaction) 0028 : mTransaction(transaction) 0029 { 0030 0031 } 0032 0033 void SynchronizerStore::recordRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId) 0034 { 0035 Index("rid.mapping." + bufferType, mTransaction).add(remoteId, localId); 0036 Index("localid.mapping." + bufferType, mTransaction).add(localId, remoteId); 0037 } 0038 0039 void SynchronizerStore::removeRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId) 0040 { 0041 Index("rid.mapping." + bufferType, mTransaction).remove(remoteId, localId); 0042 Index("localid.mapping." + bufferType, mTransaction).remove(localId, remoteId); 0043 } 0044 0045 void SynchronizerStore::updateRemoteId(const QByteArray &bufferType, const QByteArray &localId, const QByteArray &remoteId) 0046 { 0047 const auto oldRemoteId = Index("localid.mapping." + bufferType, mTransaction).lookup(localId); 0048 removeRemoteId(bufferType, localId, oldRemoteId); 0049 recordRemoteId(bufferType, localId, remoteId); 0050 } 0051 0052 QByteArray SynchronizerStore::resolveRemoteId(const QByteArray &bufferType, const QByteArray &remoteId, bool insertIfMissing) 0053 { 0054 if (remoteId.isEmpty()) { 0055 SinkWarning() << "Cannot resolve empty remote id for type: " << bufferType; 0056 return {}; 0057 } 0058 // Lookup local id for remote id, or insert a new pair otherwise 0059 Index index("rid.mapping." + bufferType, mTransaction); 0060 const QByteArray sinkId = index.lookup(remoteId); 0061 if (sinkId.isEmpty() && insertIfMissing) { 0062 const auto newId = Sink::Storage::DataStore::generateUid(); 0063 index.add(remoteId, newId); 0064 Index("localid.mapping." + bufferType, mTransaction).add(newId, remoteId); 0065 return newId; 0066 } 0067 return sinkId; 0068 } 0069 0070 QByteArray SynchronizerStore::resolveLocalId(const QByteArray &bufferType, const QByteArray &localId) 0071 { 0072 if (localId.isEmpty()) { 0073 SinkError() << "Tried to resolve an empty local id"; 0074 Q_ASSERT(false); 0075 return {}; 0076 } 0077 QByteArray remoteId = Index("localid.mapping." + bufferType, mTransaction).lookup(localId); 0078 if (remoteId.isEmpty()) { 0079 //This can happen if we didn't store the remote id in the first place 0080 SinkTrace() << "Couldn't find the remote id for " << bufferType << localId; 0081 return QByteArray(); 0082 } 0083 return remoteId; 0084 } 0085 0086 QByteArrayList SynchronizerStore::resolveLocalIds(const QByteArray &bufferType, const QByteArrayList &localIds) 0087 { 0088 QByteArrayList result; 0089 for (const auto &l : localIds) { 0090 const auto id = resolveLocalId(bufferType, l); 0091 if (!id.isEmpty()) { 0092 result << id; 0093 } 0094 } 0095 return result; 0096 } 0097 0098 QByteArray SynchronizerStore::readValue(const QByteArray &key) 0099 { 0100 QByteArray value; 0101 mTransaction.openDatabase("values").scan(key, [&value](const QByteArray &, const QByteArray &v) { 0102 value = v; 0103 return false; 0104 }, [](const Sink::Storage::DataStore::Error &) { 0105 //Ignore errors because we may not find the value 0106 }); 0107 return value; 0108 } 0109 0110 QByteArray SynchronizerStore::readValue(const QByteArray &prefix, const QByteArray &key) 0111 { 0112 return readValue(prefix + key); 0113 } 0114 0115 void SynchronizerStore::writeValue(const QByteArray &key, const QByteArray &value) 0116 { 0117 mTransaction.openDatabase("values").write(key, value); 0118 } 0119 0120 void SynchronizerStore::writeValue(const QByteArray &prefix, const QByteArray &key, const QByteArray &value) 0121 { 0122 writeValue(prefix + key, value); 0123 } 0124 0125 void SynchronizerStore::removeValue(const QByteArray &prefix, const QByteArray &key) 0126 { 0127 auto assembled = prefix + key; 0128 if (assembled.isEmpty()) { 0129 return; 0130 } 0131 mTransaction.openDatabase("values").remove(assembled, [&](const Sink::Storage::DataStore::Error &error) { 0132 SinkWarning() << "Failed to remove the value: " << prefix + key << error; 0133 }); 0134 } 0135 0136 void SynchronizerStore::removePrefix(const QByteArray &prefix) 0137 { 0138 if (prefix.isEmpty()) { 0139 return; 0140 } 0141 auto db = mTransaction.openDatabase("values"); 0142 QByteArrayList keys; 0143 db.scan(prefix, [&] (const QByteArray &key, const QByteArray &value) { 0144 keys << key; 0145 return true; 0146 }, {}, true); 0147 for (const auto &k : keys) { 0148 db.remove(k); 0149 } 0150 } 0151 0152 bool SynchronizerStore::contains(const QByteArray &key) 0153 { 0154 return !readValue(key).isEmpty(); 0155 } 0156 0157 bool SynchronizerStore::contains(const QByteArray &prefix, const QByteArray &key) 0158 { 0159 return contains(prefix + key); 0160 } 0161