1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-04 02:17:51 +01:00
Telegram/Telegraph/PSLMDBKeyValueStore.m

236 lines
5.5 KiB
Mathematica
Raw Normal View History

2014-07-10 16:11:09 +02:00
#import "PSLMDBKeyValueStore.h"
#import "lmdb.h"
#import "PSLMDBTable.h"
2015-10-01 18:19:52 +02:00
#import "PSLMDBKeyValueReaderWriter.h"
2014-07-10 16:11:09 +02:00
@interface PSLMDBKeyValueStore ()
{
NSString *_path;
MDB_env *_env;
2015-10-01 18:19:52 +02:00
PSLMDBTable *_table;
2014-07-10 16:11:09 +02:00
}
@end
@implementation PSLMDBKeyValueStore
2015-10-01 18:19:52 +02:00
+ (instancetype)storeWithPath:(NSString *)path size:(NSUInteger)size
2014-07-10 16:11:09 +02:00
{
if (path.length == 0)
return nil;
PSLMDBKeyValueStore *result = [[PSLMDBKeyValueStore alloc] init];
if (result != nil)
{
result->_path = path;
2015-10-01 18:19:52 +02:00
if (![result _open:size])
2014-07-10 16:11:09 +02:00
{
[result close];
return nil;
}
}
return result;
}
2015-10-01 18:19:52 +02:00
- (bool)_open:(NSUInteger)size
2014-07-10 16:11:09 +02:00
{
int rc = 0;
rc = mdb_env_create(&_env);
if (rc != MDB_SUCCESS)
return false;
bool createDirectory = false;
BOOL isDirectory = false;
if ([[NSFileManager defaultManager] fileExistsAtPath:_path isDirectory:&isDirectory])
{
if (!isDirectory)
{
[[NSFileManager defaultManager] removeItemAtPath:_path error:nil];
createDirectory = true;
}
}
else
createDirectory = true;
if (createDirectory)
[[NSFileManager defaultManager] createDirectoryAtPath:_path withIntermediateDirectories:true attributes:nil error:nil];
2015-10-01 18:19:52 +02:00
mdb_env_set_mapsize(_env, (size_t)size);
2014-07-10 16:11:09 +02:00
mdb_env_set_maxdbs(_env, 64);
rc = mdb_env_open(_env, [_path UTF8String], MDB_NOSYNC, 0664);
if (rc != MDB_SUCCESS)
2015-10-01 18:19:52 +02:00
{
if (rc == MDB_INVALID)
{
[[NSFileManager defaultManager] removeItemAtPath:_path error:nil];
[[NSFileManager defaultManager] createDirectoryAtPath:_path withIntermediateDirectories:true attributes:nil error:nil];
rc = mdb_env_create(&_env);
mdb_env_set_mapsize(_env, (size_t)size);
mdb_env_set_maxdbs(_env, 64);
rc = mdb_env_open(_env, [_path UTF8String], MDB_NOSYNC, 0664);
if (rc == MDB_INVALID)
return false;
}
else
return false;
}
2014-07-10 16:11:09 +02:00
int removedReaders = 0;
rc = mdb_reader_check(_env, &removedReaders);
if (removedReaders != 0)
TGLog(@"[PSLMDBKeyValueStore removed %d stale readers]", removedReaders);
2015-10-01 18:19:52 +02:00
_table = [self _createTableWithName:@"main"];
2014-07-10 16:11:09 +02:00
return true;
}
- (void)close
{
2015-10-01 18:19:52 +02:00
mdb_close(_env, _table.dbi);
2014-07-10 16:11:09 +02:00
mdb_env_close(_env);
_env = NULL;
}
- (void)sync
{
int rc = 0;
rc = mdb_env_sync(_env, 1);
if (rc != MDB_SUCCESS)
TGLog(@"[PSLMDBKeyValueStore sync: mdb_env_sync error %d]", rc);
}
- (void)panic
{
}
2015-10-01 18:19:52 +02:00
- (PSLMDBTable *)_createTableWithName:(NSString *)name
2014-07-10 16:11:09 +02:00
{
PSLMDBTable *result = nil;
if (result == nil)
{
2015-10-01 18:19:52 +02:00
int rc = 0;
MDB_txn *txn = NULL;
rc = mdb_txn_begin(_env, NULL, 0, &txn);
if (rc != MDB_SUCCESS)
2014-07-10 16:11:09 +02:00
{
2015-10-01 18:19:52 +02:00
TGLog(@"[PSLMDBKeyValueStore transaction begin failed %d]", rc);
2014-07-10 16:11:09 +02:00
2015-10-01 18:19:52 +02:00
if (rc == MDB_PANIC)
2014-07-10 16:11:09 +02:00
{
2015-10-01 18:19:52 +02:00
TGLog(@"[PSLMDBKeyValueStore critical error received]");
2014-07-10 16:11:09 +02:00
2015-10-01 18:19:52 +02:00
[self panic];
2014-07-10 16:11:09 +02:00
}
2015-10-01 18:19:52 +02:00
}
MDB_dbi dbi;
rc = mdb_dbi_open(txn, [name UTF8String], MDB_CREATE, &dbi);
if (rc != MDB_SUCCESS)
{
mdb_txn_abort(txn);
2014-07-10 16:11:09 +02:00
2015-10-01 18:19:52 +02:00
TGLog(@"[PSLMDBKeyValueStore mdb_dbi_open failed %d]", rc);
}
else
{
mdb_txn_commit(txn);
2014-07-10 16:11:09 +02:00
2015-10-01 18:19:52 +02:00
PSLMDBTable *createdTable = [[PSLMDBTable alloc] initWithDbi:dbi];
result = createdTable;
2014-07-10 16:11:09 +02:00
}
}
return result;
}
2015-10-01 18:19:52 +02:00
- (void)readInTransaction:(void (^)(id<PSKeyValueReader>))transaction
2014-07-10 16:11:09 +02:00
{
if (transaction == nil)
return;
2015-10-01 18:19:52 +02:00
PSLMDBTable *table = _table;
2014-07-10 16:11:09 +02:00
if (table != nil)
{
int rc = 0;
MDB_txn *txn = NULL;
rc = mdb_txn_begin(_env, NULL, MDB_RDONLY, &txn);
if (rc != MDB_SUCCESS)
{
TGLog(@"[PSLMDBKeyValueStore mdb_txn_begin failed %d", rc);
if (rc == MDB_PANIC)
{
TGLog(@"[PSLMDBKeyValueStore critical error received]");
[self panic];
}
}
else
{
2015-10-01 18:19:52 +02:00
transaction([[PSLMDBKeyValueReaderWriter alloc] initWithTable:table transaction:txn]);
2014-07-10 16:11:09 +02:00
rc = mdb_txn_commit(txn);
if (rc != MDB_SUCCESS)
TGLog(@"[PSLMDBKeyValueStore mdb_txn_commit error %d]", rc);
}
}
}
2015-10-01 18:19:52 +02:00
- (void)readWriteInTransaction:(void (^)(id<PSKeyValueReader, PSKeyValueWriter>))transaction
2014-07-10 16:11:09 +02:00
{
if (transaction == nil)
return;
2015-10-01 18:19:52 +02:00
PSLMDBTable *table = _table;
2014-07-10 16:11:09 +02:00
if (table != nil)
{
int rc = 0;
MDB_txn *txn = NULL;
rc = mdb_txn_begin(_env, NULL, 0, &txn);
if (rc != MDB_SUCCESS)
{
TGLog(@"[PSLMDBKeyValueStore mdb_txn_begin failed %d", rc);
if (rc == MDB_PANIC)
{
TGLog(@"[PSLMDBKeyValueStore critical error received]");
[self panic];
}
}
else
{
2015-10-01 18:19:52 +02:00
transaction([[PSLMDBKeyValueReaderWriter alloc] initWithTable:table transaction:txn]);
2014-07-10 16:11:09 +02:00
rc = mdb_txn_commit(txn);
if (rc != MDB_SUCCESS)
TGLog(@"[PSLMDBKeyValueStore mdb_txn_commit error %d]", rc);
}
}
}
@end