Jump to content

Статы...


Recommended Posts

Стоял у меня стг 2.4.02. Время от времени вываливался и недописывал статы. При этом все скрипты востановления обнуленных статов, которые есть на этом форуме, были бесполезными, так как файл не обнулен, но и не полностью записан. СТГ с такими файлами стартовать отказывался. Сейчас откатил на 2.4.01, пока вроде нормально, но сташновато, что повторится. Кто сталкивался? Как лечили?

Link to post
Share on other sites

Журналируемая ФС, УПС на сервер, перевод хранилища на БД, выкинуть сервер, улететь на луну (рекомендуется, если все прошлые методы не помогли).

Link to post
Share on other sites

".bak-файлы, .bak-файлы!"

Они должны быть вне зависимости от того дописал сервер файл или нет. Если stg падает - он не удаляет их за собой.

Link to post
Share on other sites
Журналируемая ФС, УПС на сервер, перевод хранилища на БД, выкинуть сервер, улететь на луну (рекомендуется, если все прошлые методы не помогли).

Никогда журналирующая ФС не будет спасать открытый на запись файл. Никогда в жизни. Журнал ведется не для этого. Снова и снова вопрос в криво написанной процедуре записи данных в файл.

Link to post
Share on other sites
".bak-файлы, .bak-файлы!"

Они должны быть вне зависимости от того дописал сервер файл или нет. Если stg падает - он не удаляет их за собой.

Так, как сделаны бак-файлы сейчас (по сути являясь фиктивными бак-файлами), не спасет ситуацию. Да и по сути, бак-файлы, создаваемые рядом, обычно нужны совсем для других целей (для возможности отката к предыдущей версии данных - back up, а не для их спасения).

 

Еще раз повторю - причина проблемы в том, что Борис открывает файл с данными на запись. Это делать ни в коем случае нельзя. Ни при каких условиях. В этом причина всех проблем. Но пока Борис предпочитает "незамечать" этого.

Link to post
Share on other sites
Журналируемая ФС, УПС на сервер, перевод хранилища на БД, выкинуть сервер, улететь на луну (рекомендуется, если все прошлые методы не помогли).

Никогда журналирующая ФС не будет спасать открытый на запись файл. Никогда в жизни. Журнал ведется не для этого. Снова и снова вопрос в криво написанной процедуре записи данных в файл.

Ладно уже, спасал переход на журналируемую ФС и не раз. Особенно на FreeBSD где по дефолту иногда ставилась не журналируемая ФС. Борис предлагал вам прислать патч - не хотите, не шлите, но тогда не надо в каждой теме писать "свое" мнение, ибо я тоже могу сказать что на заборе написано.

Link to post
Share on other sites
Ладно уже, спасал переход на журналируемую ФС и не раз. Особенно на FreeBSD где по дефолту иногда ставилась не журналируемая ФС.

 

Журнал ведется для того, что бы сохранить структуру файловой системы, и все. Не будет он спасать файл, открытый на запись (т.е. файл нулевой длины, он же файл, который не содержит информации). Не надо плодить очередные мифы про журнал.

 

Борис предлагал вам прислать патч - не хотите, не шлите, но тогда не надо в каждой теме писать "свое" мнение, ибо я тоже могу сказать что на заборе написано.

 

Я очень благодарен Борису за оказанную мне честь прислать ему патч. Но я не собираюсь специально ставить старгейзер, править код, отлаживать и проверять, и отсылать ему патч, ибо я не являюсь пользователем старгейзера. Скачать исхолники и заглянуть в файл file_store.cpp мне не сложно - 5-10 минут в виде отдыха не жалко. Но исправлять явную и элементарную ошибку мне некогда (да и желания нет никакого). Патчить "от балды" без проверки и отладки - не в моих правилах. В конце концов, это Борин продукт имеет дырищу в сохранении данных. Я посоветовал элементарный и общеиспользуемый алгоритм по сохранению этих данных. Пока Борис предпочитает спорить... Ну пусть спорит (а в этом время его продукт теряет данные!).

 

Я не собираюсь писать "свое" мнение об общей идее старгейзера, об неудачно выбранной структуре данных (ну пытается Борис много лет натянуть клиента на коллектор трафика - ну может это многим нравится), о выборе математической модели биллинга (в результате чего деньги считаются примерно, приблизительно, с погрешностью до 15% в месяц - да кому оно надо правильно считать-то?).

 

Но вот о элементарной ошибке работы с файлами я буду писать до тех пор, пока эта ошибка будет болтаться в продукте, и пока автору продукта до лампочки эта ошибка. Может кто-то очередной бедолага подумает лишний раз, стоит ли ставить продукт, который элементарно теряет данные, в следствие чего он принципиально не пригоден для эксплуатации.

Link to post
Share on other sites

К сожалению опять пустые слова. Если вы заглядывали в модуль (file_store.cpp) и узрели ошибку, что мешает вам поделиться идей её искоренения с авторами ? Пожалуйста, выскажите более конструктивные предложения по реализации записи файлов, чем в уже который раз высказывание про то что "ошибка где-то есть, но где и в чем искать как-то не с руки да и отлаживать сей продукт мне нету времени". Любая конструктивная критика будет воспринята и воспринимается от других, правда другие люди хоть и критикуют, однако утруждают найти время для того чтобы прислать логи/показать конкретно места кода, где по их мнению возникает ошибка. От вас же, кроме опусов о том что неправильно пишутся файлы, к сожалению конкретных предложений не поступает, а жаль.

Link to post
Share on other sites
К сожалению опять пустые слова. Если вы заглядывали в модуль (file_store.cpp) и узрели ошибку, что мешает вам поделиться идей её искоренения с авторами ? Пожалуйста, выскажите более конструктивные предложения по реализации записи файлов, чем в уже который раз высказывание про то что "ошибка где-то есть, но где и в чем искать как-то не с руки да и отлаживать сей продукт мне нету времени". Любая конструктивная критика будет воспринята и воспринимается от других, правда другие люди хоть и критикуют, однако утруждают найти время для того чтобы прислать логи/показать конкретно места кода, где по их мнению возникает ошибка. От вас же, кроме опусов о том что неправильно пишутся файлы, к сожалению конкретных предложений не поступает, а жаль.

 

Приводил я много раз свой вариант гарантированной и надежной записи данных, в результате чего Борис стал спорить со стандартами POSIX :)

 

Еще раз привести? Мне не жалко. Ибо процедура очень примитивна и проста. Привожу вариант надежного сохранения данных. И так, если мы хотим обновить данные в каком-либо файле, делаем, как раз-два-три:

 

1) Создаем временный файл, с раширением, например, stat.tmp%d, куда запихиваем, например, (int)getpid() в качестве уникального номера в системе.

 

2) Записываем все данные в этот файл. Закрываем файл (!!!) - все, файл целый и невредимый - и только тут его может спасти журнал в случае внезапного ребута!!!

 

3) Для обновления основного файла делаем rename("stat.tmp123", "stat") - POSIX гарантирует, что в любой момент времени обязан существовать либо старый, либо новый файл. Т.е. отсутствовать он не может ни при каких условиях, кроме случаев физического повреждения носителя. Т.е. файл есть всегда - целый и не нулевой.

 

ВСЕ!!!

 

Теперь при выпадении старгейзера, либо при его килянии НИКОГДА данные из файла stat не потеряются. При внезапном ребуте файл никогда не обнулится.

 

Для написания процедуры гарантированного сохранения данных в старгейзере надо делать больше изменений.

 

Так-что не надо про "опусы" и "пустые слова". Я уже задолбался каждый раз рассказывать...

Link to post
Share on other sites

Для того что-бы поддержать VOP я немного полазил в коде

 

и вот что обнаружил. Подправьте меня если я не прав ))))

 

где-то в коде

 


if (store->SaveUserConf(uc, login))
   {
   WriteServLog("Cannot write conf for user %s.", login.c_str());
   WriteServLog("%s", store->GetStrError().c_str());
   printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
   printfd(__FILE__, "%s\n", store->GetStrError().c_str());
   return -1;
   }

 

 

Смотрим что делает SaveUserConf

 


int FILES_STORE::SaveUserConf(const USER_CONF & conf, const string & login) const
{
string fileName;
fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";

BAK_FILE bakFile(fileName);

CONFIGFILE cfstat(fileName);

int e = cfstat.Error();

if (e)
   {
   errorStr = string("User \'") + login + "\' conf not written\n";
   return -1;
   }

chmod(fileName.c_str(), storeSettings.GetConfMode());
chown(fileName.c_str(), storeSettings.GetConfUID(), storeSettings.GetConfGID());

cfstat.WriteString("Password",     conf.password);
cfstat.WriteInt   ("Passive",      conf.passive);
cfstat.WriteInt   ("Down",         conf.disabled);
cfstat.WriteInt   ("AlwaysOnline", conf.alwaysOnline);
cfstat.WriteString("Tariff",       conf.tariffName);
cfstat.WriteString("Address",      conf.address);
cfstat.WriteString("Phone",        conf.phone);
cfstat.WriteString("Email",        conf.email);
cfstat.WriteString("Note",         conf.note);
cfstat.WriteString("RealName",     conf.realName);
cfstat.WriteString("Group",        conf.group);
cfstat.WriteDouble("Credit",       conf.credit);
cfstat.WriteString("TariffChange", conf.nextTariff);

char userdataName[12];
for (int i = 0; i < USERDATA_NUM; i++)
   {
   sprintf(userdataName, "Userdata%d", i);
   cfstat.WriteString(userdataName, conf.userdata[i]);
   }
cfstat.WriteInt("CreditExpire",    conf.creditExpire);

stringstream ipStr;
ipStr << conf.ips;
cfstat.WriteString("IP", ipStr.str());

return 0;
}

 

Казалось бы где ошибка?????

 

1. Нету проверки - создан ли bak файл !!!!

 

2. Создается класс CONFIGFILE cfstat(fileName) - файл открывется для записи ,

ноооооооооооооооо где fclose ???????????????????????? или flush ?????????????

 

я так понимаю после того как мы создали класс и с ним поработали нужно вызвать деструктор, в деструкторе как минимум должно стоять fclose ????

 

Значит файл мы не закрываем. Дык открыть для записи открыли- что-то туда записали, а скинуть буффер на диск не скинули !!! Подправьте меня если я не прав

Link to post
Share on other sites
Значит файл мы не закрываем. Дык открыть для записи открыли- что-то туда записали, а скинуть буффер на диск не скинули !!! Подправьте меня если я не прав

 

Вообще, в приличном обществе так bak-файл не создают. BAK-файл - это _предыдущий_ файл без каких-либо изменений, меняется только имя (что гарантирует его целостность), и создаваться он может (если это не файльшивый bak) только командочкой rename("stat", "stat.bak");

 

Далее, bak-файл создается только в тех случаях, когда запись новых данных в файл подразумевает возможность ошибки. Например, это редактор текста, в котором файл редактируется человеком, который может ошибиться - в этом случае необходим возврат к предыдущей версии файла. Вот в этом случае и создается BAK-файл. К тому же, в таких случаях, ситуация отсутсвия основного файла мкжду двумя переименованиями не критично (а в старгейзере наоборот, критично). Если файл пишется программно автоматически, то никакого возврата потребоваться не может. Поэтому в этом месте мало того, что он фиктивный (создается искуственно, а не является предыдущим файлом), так он еще и не нужен. В результате работа старгейзера неоправданно утежеляется и усложняется.

 

А деструктор должен вызываться автоматически при уходе из функции, где определен класс (может я не прав - я не программист :) )

 

Так-что рецепт простой. Фиктивный BAK убрать нафик. Процедуру записи модернизировать.

Link to post
Share on other sites
Журналируемая ФС, УПС на сервер, перевод хранилища на БД, выкинуть сервер, улететь на луну (рекомендуется, если все прошлые методы не помогли).

выкинуть биллинг... убитцо ап стену.

 

Если серьезно, то баки сервер записал ровно раз и раз их прибил... Больше баков небыло и нет. Насчет упса - сервер выпадае при работе, проблем с питанием в этот момент нет (касательно версии 2.4.02, с 2.4.01 полет пока нормальный).

Насчет скриптов защиты от обнуления вобще худо. Скрипт бэкапит недописанный стат от чего половина данных теряется наглухо.

Link to post
Share on other sites

1 я не сишник - но в делфе нужно деструктор самому вызывать

 

 

в файле confiles.cpp

 

описан деструктор

 

но указателья он явно не закрывает или я что-то не понимаю.

 

CONFIGFILE::~CONFIGFILE()
{

}

 

Я понимаю так создал класс. (в классе отрыл указатель на файл)

 

 

поработал с ним (произвел записи по указателю)

 

 

уничтожил класс (закрыл указатель)

 

Опять же подправьте меня если я не прав

 

 

вдогонку

 

int CONFIGFILE::WriteString(const string & param, const string &val)
{
param_val[param] = val;
Flush();
return 0;
}

 

флуш найден )) только непонятный какой-то

 


int CONFIGFILE::Flush()
{
fstream f(fileName.c_str(), ios::out);
if (!f.is_open())
{
error = EIO;
return EIO;
}

it = param_val.begin();
while (it != param_val.end())
   {
   f << it->first << "=" << it->second << endl;
   it++;
   }

f.close();

return 0;
}

Link to post
Share on other sites
Так-что рецепт простой. Фиктивный BAK убрать нафик. Процедуру записи модернизировать.

Дядьку, снизойди хоть до рассказать где и что в коде править :)

Я не программер (как и многие из юзающих stg)

Если авторы проэкта не хотят модернизировать свой код (по разным возможным причинам) - может быть десятку бетатестеров было бы интересно приложить патч и посмотреть что получится, самим?

Link to post
Share on other sites

думаю что рыть коды смысла нету - самый лучший вариант - перейти на работу с СУБД.

 

ибо самим исправить то что нарабатывалось годами - тяжело будет ))

Link to post
Share on other sites
Казалось бы где ошибка?????

 

1. Нету проверки - создан ли bak файл !!!!

 

2. Создается класс CONFIGFILE cfstat(fileName) - файл открывется для записи ,

ноооооооооооооооо где fclose ???????????????????????? или flush ?????????????

 

я так понимаю после того как мы создали класс и с ним поработали нужно вызвать деструктор, в деструкторе как минимум должно стоять fclose ????

 

Значит файл мы не закрываем. Дык открыть для записи открыли- что-то туда записали, а скинуть буффер на диск не скинули !!! Подправьте меня если я не прав

1. При сохранении параметров нету смысла в проверке наличия bak-файла. Он нам нужен только при чтении. BAK_FILE создает дубликат файла с расширением .bak

2. Внимательно смотри конструктор класса CONFIGFILE. Файл открывается на чтение, зачитывается, сохраняется в std::map<std::string, std::string> и закрывается. При записи строки в файл она сперва обновляется в std::map а потом вызывается Flush. Flush все содержимое std::map сбрасывает в файл (файл при этом открывается и закрывается). Вот и все.

Link to post
Share on other sites
1 я не сишник - но в делфе нужно деструктор самому вызывать

C++ очень сильно отличается от Object Pascal.

Link to post
Share on other sites

Flush все содержимое std::map сбрасывает в файл (файл при этом открывается и закрывается). Вот и все.

 

и еще я считаю совсем не корректно переписывать всегда весь файл при добавлении только одно параметра.

 

int CONFIGFILE::Flush()
{
fstream f(fileName.c_str(), ios::out);
if (!f.is_open())
{
error = EIO;
return EIO;
}

it = param_val.begin();
while (it != param_val.end())
  {
  f << it->first << "=" << it->second << endl;
  it++;
  }

f.close();

return 0;
}

 

может там нужно все внимательно пересмотреть ? может баг кроется именно в этом месте?

 

и еще может быть проверить структуру на наличие в ней данных?

 

файл для записи открыли- записали пустоту и закрыли.

 

может еще раз внимательно алгоритм пересмотреть ?

Link to post
Share on other sites
и еще я считаю совсем не корректно переписывать всегда весь файл при добавлении только одно параметра.

Ну если ты предложиш способ быстрого вычисления позиции первого символа строки в файле и корректного adjust позиции первого символа следующей строки в этом-же файле при записи строки другого размера чем она была ранее - тогда да. Но, на сегодня, это займет намного больше временеи чем удаление файла и его перезапись.

 

CONFIGFILE не знает о том какие данные должны быть в std::map и сколько. Да и не может знать - это универсальная читалка/писалка конфигов. Можно, конечно, добавить проверку на required fields или еще чего-нибуть, но при этом резко возрастут тормоза при записи. И сложность алгоритма из линейной превратится как минимум в NlogN, а то и в квадратичную.

Link to post
Share on other sites

Переходите лучше на мускуль и не парьте мозг себе и людям. Лучше думаю искать баги в модуле хранения данных в мускуле чем в файлах, это более перспективно, на то она и СУБД чтобы хранить данные, и что при ребуте данные не потеряются можно немного гарантировать. Зачем делать свою БД, если уже все давно сделано? Зачем заново создавать велосипед? Тем более, что создаете уже довольно таки долго, и не сильно-то хорошо как видно получается...

Link to post
Share on other sites

где-то в коде

 

cfstat.WriteString("RealName",     conf.realName);
cfstat.WriteString("Group",        conf.group);
cfstat.WriteDouble("Credit",       conf.credit);
cfstat.WriteString("TariffChange", conf.nextTariff);

 

прикаждом вызове WriteString

 

внутри процедуры

 

выполянется flush (который постоянно переписыват файл ) - это разве правильно и очень быстро?

Link to post
Share on other sites

А насчет предложений - разве их здесь кто-то слушает? Постоянно меряемся у кого длинее болт. Хочешь предложений - откажись от текстовых файлов - перейди на бинарные, проблем с поиском не будет - спозиционировался куда нужно и впихнул что нужно.

 

В конце концов откажитесь в финальном релизе от filestorag

 

баг со СТАТАМИ - есть был и будет до тех пор пока вместо поиска баг, будем вести безсмысленный флейм! Посему примите критику, а не отбивайтесь тем что у нас все четко.

 

XML зачем городить?

 

по-поводу XML _ почитай статью умного дядьки

 

http://russian.joelonsoftware.com/Articles/BacktoBasics.html

 

а то весь код конфигуратора (особенно серверной части ) превратили в сплошной парсер !!!!

 

VOP совершенно прав во всем ! И даже насчет подсчета траффика +-15% - он также прав что кому эти цифри нужны.Там они точно не нужны -но найдутся клиенты - которые это увидят!

 

Я как и VOP человек совсем посторонний. просто у нас билинг стоит , но когда мы решили для себя немного расширить его возможности - начали понимать в его далеко не совершенном коде и глючности - но зато авторы кричат что он работает на всех иксах - да мне пофиг что он работает на линксе -мне нужно под фрей сидеть. вот и говрю о недостатках!

Link to post
Share on other sites
Ну так переходите на mysql_store и баги испарятся...

Почему-то у меня такая уверенность, что если не можем с примитивными файлами работать, что при переходе на sql багов увеличится в разы... А надежнолсть рухнет ниже порога функциональности.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...