php i rozszerzenia w c++

Posted by vandall on 17th październik , 2014

przydatne do budowania rozszerzeń w cpp (dla php)

https://github.com/phalcon/zephir
http://pocoproject.org/

Importowanie bazy płatnik z mdb do SQL (np. 2012)

Posted by vandall on 8th sierpień , 2014

Generalnie przy pracy z programem Płatnik zazwyczaj są same problemy.

niby mamy tam opcję “migracji bazy” która mogłaby pomóc w przypadku potrzeby dogrania klienta poprzez archiwizację, standandardowo jednak – cokolwiek bardziej potrzebnego w Płatniku nie działa ;)

niby możemy przeprowadzić archiwum ale można to zrobić wyłącznie do tego samego formatu. podobnie zresztą import możliwy jest wyłącznie sql -> sql oraz access -> access.

rozwiązanie poniżej jednak zapewnia możliwość przeprowadzenia tej operacji.

korzystamy w tym celu z narzędzia Microsoft SQL Server Migration Assistant (na moment instalacji był dostępny tutaj : http://www.microsoft.com/en-us/download/confirmation.aspx?id=42656).

oczywiście toto cudo też się specjalnie w pełni nie zainstaluje samo (przynajmniej mi się nie udało ;) ) bo wymaga bibliotek Access-a. (istnieje teoria – której nie sprawdzałem – że posiadając Microsoft office n/w elementu doinstalowywać nie trzeba. jak ktoś kiedyś sprawdzi – mile widziane info do mnie ;) ).

w każdym razie aby odczytać plik mdb potrzebne będzie : Access 2007 Download: Access Runtime (ja pobrałem tutaj : http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=4438).

jeśli jeszcze nie posiadasz pliku mdb jako archiwum płatnika – zrób archiwum.

teraz troszkę szperania w configu MSSQL :
w management studio łączysz się z bazą, prawy przycisk w explorerze na twoim serwerze -> opcja “facets” -> w select wybieramy Facet “Surface and configuration” i opcję “AdHocRemoteQueriesEnabled” przerzucamy na true.

teraz odpalamy Microsoft SQL Server Migration Assistant (w wersji 32bit! to ważne!).

dalej wskazujemy wersję bazy (np MS SQL 2012).
dalej system poprosi o wskazanie pliku mdb (wskazujemy).
po chwili pracy (czytanie z tego pliku itp) możliwe już jest połączenie z serwerem SQL.
jeśli odpalimy konwersję (connect, load and migrate) okienko zapyta o wskazanie serwera sql i bazy danych (wskauzjemy NOWĄ – nie próbowałem wskazać bezpośrednio bazy płatnika bo w moim przekonaniu skasuje to aktualne dane lub je uszkodzi jeśli nie zrobimy potem importu. ale może ktoś odważny spróbuje ;) ).

po chwili przetwarzania powinna powstać nowa baza z danymi z pliku mdb (ale już w SQL!).

dzięki temu w płatniku w rejestrze wchodzimy w “odtwórz z archiwum” i cieszymy się opcją wskazania zewnętrznej bazy danych SQL uprzednio stworzonej przez konwersję. :)

zalecam po operacji przywrócić AdHocRemoteQueriesEnabled ;)

mam nadzieję, że przypadkiem nie tylko mi w/w info pomoże ;)

pzdr.

Google adwords UserList

Posted by vandall on 21st grudzień , 2013

Komunikując się z google adwords API jeśli potrzebujesz przypisać do kampanii audience (Campaign -> UserList wg nazw google API) skuteczniejszym rozwiązaniem jest przypisanie UserList do każdej AdGroup oddzielnie.

przypisując w PHP API obiekt BasicUserList (lub tożsamy) do RetargetingUserList

(przykładowo przez :)

$service = $adx->GetService(’CampaignCriterionService’, ‘v201309′);
$userList = new CriterionUserList;
$userList->userListId = $audienceId; // pobrane jak niżej w przypisaniu do adgroup
$criterion = new CampaignCriterion($campaignId, null, $userList);
$operation = new CampaignCriterionOperation();
$operation->operator = “ADD”;
$operation->operand = $criterion;
$operations[] = $operation;
$results = $service->mutate($operations);

google zwraca komunikat

SoapFault exception: [soap:Server] [CriterionError.CANNOT_ADD_CRITERIA_TYPE @ operations[0].operand.criterion]

i niewiele z tym da się zrobić.

więc lepiej zrealizować to przez :

/** stworzenie audience
$conversionType = new UserListConversionType();
$conversionType->name = $audName; // nazwa

$userList = new BasicUserList();

$userList->name = $audListName;
$userList->conversionTypes = array($conversionType);

wysłać do SOAP UserListService

a następnie przydzielić do agrup kampanii

$service = $adx->GetService(’AdGroupCriterionService’, ADWORDS_VERSION);
$operations = array();
$userList = new CriterionUserList;
$userList->userListId = $audienceId; //z poprz punktu z response
$criterion = new BiddableAdGroupCriterion;
$criterion->criterion = $userList;
$criterion->adGroupId = $adgroup; // dla każdej z adgrup.
$operation = new AdGroupCriterionOperation();
$operation->operator = “ADD”;
$operation->operand = $criterion;
$operations[] = $operation;
$results = $service->mutate($operations);

uprości to tworzenie adgrup ;)

Citrix XenServer i local storage w ovh

Posted by vandall on 14th listopad , 2013

Serwerownia ovh oferuje całkiem wygodne w użyciu (choć ze stabilnością – różnie ;) ) narzędzia do samodzielnego zarządzania serwerami. jedna z funkcjonalności to możliwość preinstalacji citrix XenServer. do średnio rozbudowanych projektów nie wymagających dostępności online klasy Tier IV i wyżej sprawdza się to całkiem nieźle.

niestety jednak standardowy szablon instalacji średnio radzi sobie z dyskami (a dokładnie z LocalStorage).

Podobnie jest z dodawaniem nowych dysków.

w przypadku gdyby była potrzeba ręcznego zestawienia storage z pomocą przyjdzie taka komenda :

xe sr-create content-type=user device-config:device=/dev/sda3 host-uuid=qwe-qwe-qwe-qwe name-label=”LocalStorage” shared=false type=lvm

gdzie :
* w przypadku definiowania nowego serwera (jeśli nie widać automatycznie storage) wprowadzamy partycję pierwszego dysku
* w przypadku dodawania nowych dysków – wprowadzamy “nową” literkę.
* host-uuid to informacja osiągalna z XenCenter (zakładka general)
* name-label to nazwa widoczna w xencenter (w zasadzie dowolna)
* type lvm – pozwala na pewne operacje później dot. archiwizacji
* shared=false – podłączony w ten sposób dysk nie może być współdzielony.

poprawnie uruchomiona komenda stworzy dysk :)

pomocne przy poszukiwaniach napewno będą :
* cat /proc/partitions
* xe pbd-list (lista gdzie podłączany jest storage)
* xe sr-list (lista storage repo)

wycofanie niechcący dodanego pliku (svn)

Posted by vandall on 23rd marzec , 2013

Gdy przypadkiem dodasz za dużo do repozytorium svn (ale jeszcze nie commitowałeś) zawsze można :

svn revert –keep-local plik.txt

parametr “–keep-local” powoduje że svn nie kasuje pliku z lokalnego fs.

oczywiście polecałbym kopię bezpieczeństwa ;)

HA dla adresów IP

Posted by vandall on 18th marzec , 2013

szybki i prosty sposób jak skonfigurować adres IP tak, by był dostępny na 2 maszynach.

ten pomysł powoduje przygotowanie 2 firewalii “współdzielących” między sobą adres IP oraz maszynę za nimi do serwowania contentu.

1. potrzebny serwer, który prezentuje usługę (nie musi to być www ale tym posłużę się w opisie) : jego IP prywatne to będzie 192.168.1.1

2. firewall na który trafia ruch : jego IP prywatne to będzie 192.168.0.1

3. z oczywistych względów potrzebny nam drugi firewall : konfiguracja przewiduje zmianę tej maszyny w przypadku awarii jednej z nich : IP 192.168.0.2

4. publiczny adres IP mozliwy do przypisania do dwóch maszyn (jeżeli to jest niemożliwe do uzyskania – patrz koniec tekstu i instalacja keepalive na końcówkach).

konfigurujemy tak :

1. maszyna serwująca (192.168.1.1) robi to co robiła czyli po prostu jest (ma serwować content)

2. na każdej z pozostałych maszyn instalujemy keepalived (emerge keepalived dla gentoo, aptitude install keepalived dla ubuntu)

3. konfigurujemy na obu keepalived dla tego adresu (idea keepalived jest taka iż dokładnie jedna z maszyn z puli wskazanej przez keepalived będzie miała ten adres). konfiguracja ogranicza się do wskazania w keepalived maszyn, które adres otrzymują (po prywatnym IP) oraz IP który jest współdzielony. w kernelu trzeba uruchomić opcję “shared IP”. (konkretnie sysctl)

4. firewall na obu maszynach powinien mieć te same reguły – ruch z publicznego IP kieruje na 192.168.1.1 (w przykładzie – porty 80 i 443)

w przypadku niemożności przypisania jednego publicznego IP do 2 maszyn (zdarza się pewnie) wstawiamy na firewallu jeden IP a duplikujemy maszyny prywatne. wtedy na nich instalujemy keepalived (po adresacji prywatnej). wada : firewall wciąż może paść. ale unikamy awarii pojedyńczego hosta serwującego content. można też pomiędzy firewallem a hostem prezentującym content (hostami, bo inaczej mały to ma sens ;) ) wstawić reverse proxy (np. haproxy) które dostanie adresację prywatną i będzie kierować ruch na końcówki ale samo w sobie będzie miało wirtualne IP współdzielone.

zbieranie tresci powiazanych tabel

Posted by vandall on 12th wrzesień , 2012

Z góry uprzedzam – nie zalecam korzystać w wysokoobciążonych serwisach ani jako rozwiązania produkcyjnego. pomysł – w systemach, gdzie w różnych tabelach leżą wartości kumulowane w jednej tabeli wiążącej pozwala pobrać treść wszystkich przypisanych wartości.

np. jeżeli mamy elementy, do których są atrybuty, których same wartości słownikowane są w zależności od typu w różnych tabelach (a bywa, że tak jest optymalniej).
potrzebujemy do jakiegoś celu pobrać wartość niezależnie od tego gdzie leży i to jednym query.

zapytania też nie są pięknie sprawne ale sposób ma szanse komuś pomóc :)

opiera się na cocnat() od selectów z różnych tabel.

próba z group_concat na podzapytaniach z union w mysql niestety niekoniecznie sprawdza się (podzapytanie w podzapytaniu – które byłoby tu potrzebne nie posiada danych z zapytania podstawowego co w efekcie nie pozwala odpowiednio filtrować).

create table attribs(
id int,
type enum(’texts’, ‘attribute’),
name varchar(20)
) engine=innodb;
create table attribute (
id int,
name varchar(20),
active tinyint
) engine=innodb;
create table texts (
id int,
value varchar(20),
active tinyint
) engine=innodb;

SELECT DISTINCT
(…),
concat(
case
when (select n_ta.name from attribute n_ta where n_ta.id = tpa.id
and n_ta.active = 1 limit 1) is null
then ”
else (select group_concat(n_ta.name separator ‘ ‘) from attribute
n_ta where n_ta.id = tpa.id and n_ta.active = 1 )
end,
case
when (select n_tt.value from texts n_tt where n_tt.id = tpa.id and
n_tt.active = 1 limit 1) is null
then ”
else (select group_concat(n_tt.value separator ‘ ‘) from texts n_tt
where n_tt.id = tpa.id and n_tt.active = 1)
end
) as fullVal

FROM attribs AS tpa
(…)
;

Relatywne skrypty i css w przeglądarce

Posted by vandall on 12th wrzesień , 2012

Wiele rozwiązań w sieci (od największych, do mniejszych) stosowało rozmaite zabiegi dotyczące rozpoznawania czy jesteśmy w trybie SSL czy nie w przeglądarce. jak zapewne wiadomo poruszając się po stronie w SSL elementy ze zwykłego HTTP powodują “wredny” komunikat.

w każdym razie zamiast kombinować z https itp można wykorzystać relatywne do protokołu linki do elementów :

<img src=”//moja.domena.pl/plik-js.js” alt=”" />

to wyklucza konieczność budowania zależności dot. document.location, protocol i wielu innych magicznych trików :) polecam uproszczenia ;)

awaryjne duplikowanie maszyny

Posted by vandall on 30th sierpień , 2012

jeżeli potrzeba awaryjnie (albo i nie) zduplikować maszynę – czasami się zdarzyć może jeden ze sposobów to przeniesienie dysku na inną maszynę. jeżeli sprzętowo są zgodne (na poziomie architektury) to powinno ruszyć bez problemu (z dokładnością do ew. tuningu kernela i driverów). w wirtualkach jednak sprawuje się znakomicie.

opis sposobu na wirtualce:
1. konfigurujemy drugą maszynę o identycznych parametrach (przede wszystkim rozmiar(y) dysków)
2. oba odpalamy z livecd, konfigurujemy sieć i ssh
3. na DOCELOWEJ maszynie robimy taki myk :

ssh 192.168.111.232 “dd if=/dev/sda” | dd of=”/dev/sda”

gdzie 192.168.111.232 – to IP źródłowej maszyny.

oczywiście zakładamy że userzy to root (tak, w tym przypadku to konieczne).

w/w powtarzaj dla każdego kopiowanego dysku.

Rozwiązanie zadziała zawsze, gdy rozmiar dysku będzie zgodny. w innych przypadkach można kopiować pojedyńcze partycje, system plików, albo klasycznie przesuwać serwer.

w/w przydatne jest na niższym poziomie jeśli źródłem jest partycja lvm snapshot (pozwala na kopie stanu serwera praktycznie w locie ale pełne zastosowanie w innym miejscu…).

php, referencje, backtrace

Posted by vandall on 18th sierpień , 2012

korzystając z PHP czasem potrzeba budować dość zaawansowane realizacje. przykładowo obsługa błędów oraz związane z nimi operacje często będzie wymagać korzystania z obiektów z grupy Reflection, funkcji typu debug_backtrace() itp.

korzystając z tej ostatniej do jakichkolwiek zastosowań pamiętaj, że w całym trace (np. stosie wywołań) posiada referencje do tego, co zostało przekazane. jeżeli więc wykonasz na nich operacje licz się z tym, że zmienisz ich zawartość (Co może mieć duże znaczenie przy rozbudowanych klasach wyjątków zbierających stan systemu z momentu błędu).

przykładowo :

jeśli w funkcji function a(&$b){/*tu gdzieś nastąpił błąd */} padnie błąd. przekierowane to zostanie do obsługi błędów, tam aby pobrać dokładne informacje skorzystasz z debug_backtrace (lub innego dostępu do stosu wywołania) pracujesz na referencji. i np. realizując rzutowanie do prezentacji zmienisz te zmienne. W wyjątkach używaj kopii danych – bezpieczniejsze ;)