Часть ответа заключается в том, чтобы хранить индекс имен пользователей, которые вы проверяете в своих правилах безопасности:
app : {
users: {
"some-user-uid": {
email: "test@test.com"
username: "myname"
}
},
usernames: {
"myname": "some-user-uid"
}
}
Таким образом узел usernames
сопоставляет имя пользователя с uid. Он по существу читает, что «имя пользователя« myname »принадлежит« some-user-uid ».
С помощью этой структуры данных ваши правила безопасности могут проверить, есть ли уже запись для данного имени пользователя:
"users": {
"$uid": {
".write": "auth !== null && auth.uid === $uid",
".read": "auth !== null && auth.provider === 'password'",
"username": {
".validate": "
!root.child('usernames').child(newData.val()).exists() ||
root.child('usernames').child(newData.val()).val() == $uid"
}
}
}
Это подтверждает, что имя пользователя еще не заявлено кем-либо еще, или оно заявлено текущим пользователем.
Вот код, который я использую, чтобы удостовериться, что файл не заблокирован другим процессом. Это не является на 100% надежным, но это сделало задание большую часть времени:
/// <summary>
/// Blocks until the file is not locked any more.
/// </summary>
/// <param name="fullPath"></param>
bool WaitForFile(string fullPath)
{
int numTries = 0;
while (true)
{
++numTries;
try
{
// Attempt to open the file exclusively.
using (FileStream fs = new FileStream(fullPath,
FileMode.Open, FileAccess.ReadWrite,
FileShare.None, 100))
{
fs.ReadByte();
// If we got this far the file is ready
break;
}
}
catch (Exception ex)
{
Log.LogWarning(
"WaitForFile {0} failed to get an exclusive lock: {1}",
fullPath, ex.ToString());
if (numTries > 10)
{
Log.LogWarning(
"WaitForFile {0} giving up after 10 tries",
fullPath);
return false;
}
// Wait for the lock to be released
System.Threading.Thread.Sleep(500);
}
}
Log.LogTrace("WaitForFile {0} returning true after {1} tries",
fullPath, numTries);
return true;
}
Очевидно, можно настроить тайм-ауты и повторения для удовлетворения приложению. Я использую это для обработки огромных файлов FTP, которые требуют времени, чтобы быть записанными.
Вы могли, возможно, создать файл с временным именем ("данные xml_TMP"), и когда это - готовое изменение имя к тому, что это, как предполагается. Тем путем никакой другой процесс не будет получать доступ к нему, прежде чем это будет готово.
Если Вы соединяете объект, хранивший как помехи затем, блокировка должна работать на все потоки в том же Домене приложения, но возможно необходимо загрузить пример кода, таким образом, мы можем взглянуть на незаконные строки.
Тем не менее одна мысль состояла бы в том, чтобы проверить, настроен ли IIS для выполнения в режиме Web Garden (т.е. больше чем 1 процесс, выполняющий приложение), который повредил бы логику блокировки. В то время как Вы могли зафиксировать такую ситуацию со взаимным исключением, будет легче реконфигурировать Ваше приложение для выполнения в единственном процессе, хотя Вы были бы мудры проверить производительность прежде и после питания с веб-настройками сада, поскольку это может потенциально влиять на производительность.
Хорошо, я работал над этим и закончил тем, что создал модуль стресс-теста, чтобы в основном ковать дерьмо из моего кода от нескольких потоков (См. Связанный Вопрос).
Было намного легче с этого момента найти дыры в моем коде. Оказывается, что мой код не был на самом деле далек, но был определенный логический путь, в который это могло войти, к которым в основном вызванным операциям чтения-записи сложить, имея в виду если бы они не стали очищенными вовремя, то это пошло бы бум!
После того как я вынул это, выполнил мой стресс-тест снова, все хорошо работали!
Так, я действительно не сделал ничего специального в своем коде доступа к файлу, просто гарантировал, что я использовал lock
операторы в соответствующих случаях (т.е. при чтении или записи).