mirror of
https://github.com/danog/Telegram.git
synced 2024-11-30 04:29:15 +01:00
269 lines
10 KiB
Objective-C
269 lines
10 KiB
Objective-C
#import "PSLMDBKeyValueReaderWriter.h"
|
|
|
|
#import "PSLMDBTable.h"
|
|
#import "PSLMDBKeyValueCursor.h"
|
|
|
|
@interface PSLMDBKeyValueReaderWriter ()
|
|
{
|
|
PSLMDBTable *_table;
|
|
MDB_dbi _dbi;
|
|
MDB_txn *_txn;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation PSLMDBKeyValueReaderWriter
|
|
|
|
- (instancetype)initWithTable:(PSLMDBTable *)table transaction:(MDB_txn *)transaction
|
|
{
|
|
self = [super init];
|
|
if (self != nil)
|
|
{
|
|
_table = table;
|
|
_dbi = table.dbi;
|
|
_txn = transaction;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (bool)readValueForRawKey:(PSConstData *)key value:(PSConstData *)value
|
|
{
|
|
if (key == NULL)
|
|
return false;
|
|
|
|
MDB_val mdbKey;
|
|
MDB_val mdbData;
|
|
|
|
mdbKey.mv_data = (uint8_t *)key->data;
|
|
mdbKey.mv_size = (size_t)key->length;
|
|
|
|
int rc = 0;
|
|
rc = mdb_get(_txn, _dbi, &mdbKey, &mdbData);
|
|
|
|
if (rc == MDB_SUCCESS)
|
|
{
|
|
if (value != NULL)
|
|
{
|
|
value->data = mdbData.mv_data;
|
|
value->length = (NSUInteger)mdbData.mv_size;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (rc != MDB_NOTFOUND)
|
|
NSLog(@"[PSLMDBKeyValueReader mdb_get error %d]", rc);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
- (void)writeValueForRawKey:(const uint8_t *)key keyLength:(NSUInteger)keyLength value:(const uint8_t *)value valueLength:(NSUInteger)valueLength
|
|
{
|
|
if (key == NULL || keyLength == 0)
|
|
return;
|
|
|
|
MDB_val mdbKey;
|
|
MDB_val mdbData;
|
|
|
|
mdbKey.mv_data = (uint8_t *)key;
|
|
mdbKey.mv_size = keyLength;
|
|
|
|
mdbData.mv_data = (uint8_t *)value;
|
|
mdbData.mv_size = valueLength;
|
|
|
|
int rc = 0;
|
|
rc = mdb_put(_txn, _dbi, &mdbKey, &mdbData, 0);
|
|
|
|
if (rc != MDB_SUCCESS)
|
|
NSLog(@"[PSLMDBKeyValueWriter mdb_put error %d]", rc);
|
|
}
|
|
|
|
- (void)readWithCursor:(void (^)(PSLMDBKeyValueCursor *))readWithCursorBlock
|
|
{
|
|
if (!readWithCursorBlock)
|
|
return;
|
|
|
|
MDB_cursor *cursor = NULL;
|
|
int rc = 0;
|
|
rc = mdb_cursor_open(_txn, _dbi, &cursor);
|
|
if (rc == MDB_SUCCESS)
|
|
{
|
|
readWithCursorBlock([[PSLMDBKeyValueCursor alloc] initWithTable:_table transaction:_txn cursor:cursor]);
|
|
|
|
mdb_cursor_close(cursor);
|
|
}
|
|
else
|
|
NSLog(@"[PSLMDBKeyValueWriter mdb_cursor_open error %d]", rc);
|
|
}
|
|
|
|
- (bool)readValueBetweenLowerBoundKey:(PSConstData *)lowerBoundKey upperBoundKey:(PSConstData *)upperBoundKey selectKey:(PSKeyValueReaderSelectKey)selectKey selectedKey:(PSConstData *)selectedKey selectedValue:(PSConstData *)selectedValue
|
|
{
|
|
__block bool result = false;
|
|
|
|
[self enumerateKeysAndValuesBetweenLowerBoundKey:lowerBoundKey upperBoundKey:upperBoundKey options:selectKey == PSKeyValueReaderSelectHigherKey ? PSKeyValueReaderEnumerationReverse : 0 withBlock:^(PSData *key, PSData *value, bool *stop)
|
|
{
|
|
if (selectedKey)
|
|
*selectedKey = *key;
|
|
if (selectedValue)
|
|
*selectedValue = *value;
|
|
|
|
if (stop)
|
|
*stop = true;
|
|
|
|
result = true;
|
|
}];
|
|
|
|
return result;
|
|
}
|
|
|
|
- (void)enumerateKeysAndValuesBetweenLowerBoundKey:(PSConstData *)lowerBoundKey upperBoundKey:(PSConstData *)upperBoundKey options:(NSInteger)options withBlock:(void (^)(PSConstData *key, PSConstData *value, bool *stop))block
|
|
{
|
|
if (!block || upperBoundKey == NULL || lowerBoundKey == NULL)
|
|
return;
|
|
|
|
[self readWithCursor:^(PSLMDBKeyValueCursor *cursor)
|
|
{
|
|
MDB_val upperBoundKeyVal = {.mv_data = (uint8_t *)upperBoundKey->data, .mv_size = upperBoundKey->length};
|
|
MDB_val lowerBoundKeyVal = {.mv_data = (uint8_t *)lowerBoundKey->data, .mv_size = lowerBoundKey->length};
|
|
|
|
if (options & PSKeyValueReaderEnumerationReverse)
|
|
{
|
|
uint8_t const *positionedKey = upperBoundKey->data;
|
|
NSUInteger positionedKeyLength = upperBoundKey->length;
|
|
|
|
uint8_t const *positionedValue = NULL;
|
|
NSUInteger positionedValueLength = 0;
|
|
|
|
if ([cursor positionAt:&positionedKey keyLength:&positionedKeyLength value:&positionedValue valueLength:&positionedValueLength directionIfNotFound:PSKeyValueCursorDirectionBack])
|
|
{
|
|
MDB_val positionedKeyVal = {.mv_data = (uint8_t *)positionedKey, .mv_size = positionedKeyLength};
|
|
|
|
bool continueSearch = true;
|
|
|
|
if ((options & PSKeyValueReaderEnumerationUpperBoundExclusive) && mdb_cmp(_txn, _dbi, &upperBoundKeyVal, &positionedKeyVal) == 0)
|
|
{
|
|
continueSearch = [cursor previous:&positionedKey keyLength:&positionedKeyLength value:&positionedValue valueLength:&positionedValueLength];
|
|
}
|
|
|
|
if (continueSearch)
|
|
{
|
|
int cmpResult = mdb_cmp(_txn, _dbi, &positionedKeyVal, &lowerBoundKeyVal);
|
|
if ((options & PSKeyValueReaderEnumerationLowerBoundExclusive) ? (cmpResult > 0) : (cmpResult >= 0))
|
|
{
|
|
bool stop = false;
|
|
PSData positionedKeyData = {.data = (uint8_t *)positionedKey, .length = positionedKeyLength};
|
|
PSData positionedValueData = {.data = (uint8_t *)positionedValue, .length = positionedValueLength};
|
|
block(&positionedKeyData, &positionedValueData, &stop);
|
|
|
|
while (!stop)
|
|
{
|
|
if (![cursor previous:&positionedKey keyLength:&positionedKeyLength value:&positionedValue valueLength:&positionedValueLength])
|
|
break;
|
|
|
|
MDB_val positionedKeyVal = {.mv_data = (uint8_t *)positionedKey, .mv_size = positionedKeyLength};
|
|
|
|
int cmpResult = mdb_cmp(_txn, _dbi, &positionedKeyVal, &lowerBoundKeyVal);
|
|
if ((options & PSKeyValueReaderEnumerationLowerBoundExclusive) ? (cmpResult > 0) : (cmpResult >= 0))
|
|
{
|
|
PSData positionedKeyData = {.data = (uint8_t *)positionedKey, .length = positionedKeyLength};
|
|
PSData positionedValueData = {.data = (uint8_t *)positionedValue, .length = positionedValueLength};
|
|
block(&positionedKeyData, &positionedValueData, &stop);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uint8_t const *positionedKey = lowerBoundKey->data;
|
|
NSUInteger positionedKeyLength = lowerBoundKey->length;
|
|
|
|
uint8_t const *positionedValue = NULL;
|
|
NSUInteger positionedValueLength = 0;
|
|
|
|
if ([cursor positionAt:&positionedKey keyLength:&positionedKeyLength value:&positionedValue valueLength:&positionedValueLength directionIfNotFound:PSKeyValueCursorDirectionForward])
|
|
{
|
|
MDB_val positionedKeyVal = {.mv_data = (uint8_t *)positionedKey, .mv_size = positionedKeyLength};
|
|
|
|
bool continueSearch = true;
|
|
if ((options & PSKeyValueReaderEnumerationLowerBoundExclusive) && mdb_cmp(_txn, _dbi, &lowerBoundKeyVal, &positionedKeyVal) == 0)
|
|
{
|
|
continueSearch = [cursor next:&positionedKey keyLength:&positionedKeyLength value:&positionedValue valueLength:&positionedValueLength];
|
|
}
|
|
|
|
if (continueSearch)
|
|
{
|
|
int cmpResult = mdb_cmp(_txn, _dbi, &positionedKeyVal, &upperBoundKeyVal);
|
|
if ((options & PSKeyValueReaderEnumerationUpperBoundExclusive) ? (cmpResult < 0) : (cmpResult <= 0))
|
|
{
|
|
bool stop = false;
|
|
PSData positionedKeyData = {.data = (uint8_t *)positionedKey, .length = positionedKeyLength};
|
|
PSData positionedValueData = {.data = (uint8_t *)positionedValue, .length = positionedValueLength};
|
|
block(&positionedKeyData, &positionedValueData, &stop);
|
|
|
|
while (!stop)
|
|
{
|
|
if (![cursor next:&positionedKey keyLength:&positionedKeyLength value:&positionedValue valueLength:&positionedValueLength])
|
|
break;
|
|
|
|
MDB_val positionedKeyVal = {.mv_data = (uint8_t *)positionedKey, .mv_size = positionedKeyLength};
|
|
|
|
int cmpResult = mdb_cmp(_txn, _dbi, &positionedKeyVal, &upperBoundKeyVal);
|
|
if ((options & PSKeyValueReaderEnumerationUpperBoundExclusive) ? (cmpResult < 0) : (cmpResult <= 0))
|
|
{
|
|
PSData positionedKeyData = {.data = (uint8_t *)positionedKey, .length = positionedKeyLength};
|
|
PSData positionedValueData = {.data = (uint8_t *)positionedValue, .length = positionedValueLength};
|
|
block(&positionedKeyData, &positionedValueData, &stop);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (bool)deleteValueForRawKey:(PSData *)key
|
|
{
|
|
if (key == NULL || key->data == NULL || key->length == 0)
|
|
return false;
|
|
|
|
MDB_val mdbKey;
|
|
mdbKey.mv_data = (uint8_t *)key->data;
|
|
mdbKey.mv_size = (size_t)key->length;
|
|
|
|
int rc = 0;
|
|
rc = mdb_del(_txn, _dbi, &mdbKey, NULL);
|
|
|
|
if (rc != MDB_SUCCESS && rc != MDB_NOTFOUND)
|
|
NSLog(@"[PSLMDBKeyValueWriter mdb_del error %d]", rc);
|
|
|
|
return rc == MDB_SUCCESS;
|
|
}
|
|
|
|
- (void)deleteAllValues
|
|
{
|
|
MDB_cursor *cursor = NULL;
|
|
int rc = 0;
|
|
rc = mdb_cursor_open(_txn, _dbi, &cursor);
|
|
if (rc == MDB_SUCCESS)
|
|
{
|
|
rc = mdb_cursor_get(cursor, NULL, NULL, MDB_FIRST);
|
|
while (rc == MDB_SUCCESS)
|
|
{
|
|
rc = mdb_cursor_del(cursor, 0);
|
|
rc = mdb_cursor_get(cursor, NULL, NULL, MDB_NEXT);
|
|
}
|
|
mdb_cursor_close(cursor);
|
|
}
|
|
}
|
|
|
|
@end
|