00001 /* 00002 * Copyright (C) 2009, Edmundo Albuquerque de Souza e Silva. 00003 * 00004 * This file may be distributed under the terms of the Q Public License 00005 * as defined by Trolltech AS of Norway and appearing in the file 00006 * LICENSE.QPL included in the packaging of this file. 00007 * 00008 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING 00009 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00010 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, 00011 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 00012 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 00013 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 00014 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 * 00016 * Thanks: Jose Renato Santos 00017 * 00018 */ 00019 00020 /////////////////////////////////////////////////////////////////////////////// 00021 // DiskMgr.h -- manager disks (& implicititly nodes) 00022 // also includes "Disk" class too 00023 /////////////////////////////////////////////////////////////////////////////// 00024 00025 #include "RioUnix.h" 00026 #include "RioTypes.h" 00027 #include "ServerTypes.h" 00028 #include "DiskMgrTypes.h" 00029 #include "BitMap.h" 00030 #include "Router.h" 00031 #include "vsisocket.h" 00032 00033 class Disk; 00034 class SNode; 00035 00036 /////////////////////////////////////////////////////////////////////////////// 00037 class DiskMgr 00038 { 00039 00040 public: 00041 DiskMgr(); 00042 ~DiskMgr(); 00043 00044 // Agora o metodo Initialize da classe DiskMgr possuira somente um 00045 // parametro, a estrutura do tipo DiskMgrConfig com todos os 00046 // parametos anteriores da funcao (esta estrutura esta descrita 00047 // no arquivo DiskMgrTypes.h). 00048 int Initialize( DiskMgrConfig *Config ); 00049 // Novo parametro Connect para indicar se devemos ou nao criar a conexao 00050 // com o servidor de armazenamento. Este paramtro e usado para criar o 00051 // no do servidor, nao ativo, caso nao seja possivel, ao iniciar o 00052 // servidor de gerenciamento, se conectar a um servidor de 00053 //armazenamento. 00054 int BuildNode( char *hostname, bool Connect ); 00055 int Start(); 00056 int Stop(); 00057 int CleanUp(); 00058 // O novo parametro e um vetor de bits que indica quais servidores de 00059 // armazenamento nao podem ser usados por um cliente (cada bit esta 00060 // associado a um servidor e um valor 1 neste bit indica que o servidor 00061 // nao pode ser usado). 00062 int AllocMult( int numReplicas, RioDiskBlock *rep, 00063 unsigned long long int ExcludeStorages ); 00064 // O novo parametro e um vetor de bits que indica quais servidores de 00065 // armazenamento nao podem ser usados por um cliente (cada bit esta 00066 // associado a um servidor e um valor 1 neste bit indica que o servidor 00067 // nao pode ser usado). 00068 int Alloc( RioDiskBlock *rep, unsigned long long int ExcludeStorages ); 00069 int Free( RioDiskBlock *rep ); 00070 int Reset(); 00071 int Confirm(); 00072 int Format(); 00073 void SendStorageNode( EventStorageRequest* event, u16 DiskId ); 00074 00075 int GetNumberOfStorageNodes( unsigned int *NumberOfStorageNodes ); 00076 int GetStorageNodeInfo( unsigned int StorageNodeIndex, 00077 RioStorageNodeInfo* StorageNodeInfo ); 00078 int GetDiskStorageNodeInfo( unsigned int DiskId, 00079 RioStorageNodeInfo* StorageNodeInfo ); 00080 int GetMaxNumberOfDisks(); 00081 int GetNumberOfActiveDisks( unsigned int *NumberOfDisks ); 00082 int GetDiskName( unsigned int DiskId, char *DiskName ); 00083 int GetDiskServiceTime( EventStorageRequest* event, u16 DiskId ); 00084 unsigned int GetDiskNumberOfFreeBlocks( unsigned int DiskId ); 00085 00086 /** 00087 * Funcao para obter todos os enderecos (pares IP e porta) dos Storage 00088 * Servers (que estao listados no arquivo RIOdisk.cfg). 00089 * @param ServerAddress vetor de estruturas SOCKADDR_IN que armazenara, 00090 * em cada uma de suas entradas, um par IP, porta de um Storage Server. 00091 * @return 0 (pois algumas funcoes da classe DiskMgr retornam um valor, 00092 * mesmo que seja sempre igual a 0). 00093 */ 00094 int GetStorageServersAddress( SOCKADDR_IN *ServerAddress ); 00095 00096 /** 00097 * Nova funcao, usada pelo gerenciamento de logs, para colocar um 00098 * evento na fila de eventos (com mensagens a serem enviadas) ao 00099 * servidor de armazenamento identificado pelo IP dado com parametro. 00100 * Obs: estamos supondo que o IP do servidor de armazenameno para a 00101 * conexao TCP e o mesmo do que o da conexao UDP. 00102 * @return S_OK se existe um servidor de armazenamento com este IP, ou 00103 * o valor ERROR_UNEXPECTED se nao existir um servidor com o IP. 00104 */ 00105 int SendStorageNodeByIP( EventStorageRequest* event, u32 StorageIP ); 00106 00107 /** 00108 * Nova funcao para obter o numero de replicacoes de cada bloco. 00109 * @return numero de replicacoes para cada bloco. 00110 */ 00111 int GetNumberOfReplications( void ); 00112 /** 00113 * Nova funcao para retornar o numero minimo de discos necessarios 00114 * para inicializar as estruturas do servidor. O valor retornado sera 00115 * a soma do numero descrito a seguir para cada um dos servidores de 00116 * armazenamento. Para cada servidor de armazenamento, se ele tiver 00117 * inicializado antes do servidor de gerenciamento o valor sera o 00118 * numero de disco deste servidor e, em caso contrario, o numero 00119 * maximo de discos, ou seja, SNode::sn_maxdisks = MAXSTORAGEDISKSARRAY 00120 * @return Numero maximo de discos a serem usados. 00121 */ 00122 int GetNumberOfNeededDisks( unsigned int *NumberOfDisks ); 00123 00124 // -------------------------------------------------------------------- 00125 00126 private: 00127 int m_BlockSize; 00128 int m_MaxDisks; 00129 int m_MaxReps; 00130 char *m_MetaRoot; 00131 CRouter *m_Router; 00132 CSystemManager *m_SystemManager; 00133 int m_cntAllocMult; 00134 int m_cntAllocRetry; 00135 int m_cntAllocFail; 00136 00137 pthread_mutex_t m_mutex; 00138 00139 int m_numDisks; // max number of disks 00140 // (for each storage adds sn_maxdisks (4) ) 00141 // used to calcute the index to the disk for 00142 // the m_disks array 00143 // Node 1 indexes [1..4] 00144 // Node 2 indexes [5..8] 00145 00146 Disk **m_disks; // array of ptrs to Disk by m_diskid 00147 00148 int m_NumberOfActiveDisks; // current number of disks 00149 int m_NumberOfStorageNodes;// current number of built nodes 00150 ofstream m_log; // log file 00151 // -------------------------------------------------------------------- 00152 00153 int m_diskanum; 00154 Disk **m_diska; // allocate possible disks array 00155 00156 Disk *m_disklist; 00157 SNode *m_nodelist; 00158 00159 pthread_t m_thread; 00160 int m_termflag; 00161 00162 // Novo parametro que armazena o diretorio com o arquivo de 00163 // configuracao RIOdisk.cfg (pois ele e usado pela funcao 00164 // ReadConfiguration). 00165 char *m_ConfigsDirectory; 00166 // Novos campos usados para fazermos mais de uma tentativa ao 00167 // conectarmos com os servidores de armazenamento definidos em 00168 // RIOdisk.cfg. 00169 unsigned int m_MaxAttempts; 00170 unsigned int m_TimeBetweenAttempts; 00171 00172 // Variavel usada para contabilizar os servidores de armazenamento que 00173 // possuem espaco disponivel em um dos seus discos. Cada bit i esta 00174 // associado a um servidor de armazenamento com a identificacao i e, 00175 // se for igual a 1, indica que existe espaco em pelo menos um dos 00176 // discos do servidor (note que se este bit for 0, entao todos os discos 00177 // do servidor estarao cheios). 00178 unsigned long long int m_storagesnotfull; 00179 00180 // Variavel booleana que, quando for igual a true, indica que o servidor 00181 // foi inicializado para formatar os discos. E necessario sabermos disso 00182 // porque, neste caso, precisamos garantir que todos os servidores de 00183 // armazenamento sejam inicializados. 00184 bool m_IsFormatting; 00185 00186 int ReadConfiguration(); 00187 void BuildAlloc(); 00188 bool CheckDiskAlloc( int num, RioDiskBlock *rep, int choice ); 00189 00190 /** 00191 * Nova funcao para carregar os BitMaps dos discos associados a um 00192 * servidor de armazenamento. Esta funcao e usada para carragar os 00193 * BitMaps do disco associados a um servidor de armazenamento que 00194 * inicializou depois do servidor de gerenciamento, pois neste caso 00195 * estes BitMaps nao vao ter sido carragados pela funcao Start da 00196 * classe DiskMgr. 00197 * @param StorageId identificador do servidor de armazenamento. 00198 * servidor de armazenamento. 00199 * @return S_OK se nenhum erro ocorreu ao carragar os bitmaps ou o 00200 * codigo de erro caso nao tenha sido possivel carragar um dos bitmaps. 00201 */ 00202 int LoadDisksBitMaps( unsigned int StorageId ); 00203 /** 00204 * Nova funcao para liberar os blocos salvos no arquivo de um servidor 00205 * de armazenamento. Estes blocos foram salvos porque, ao libera-los, 00206 * o servidor de armazenamento ainda nao tinha inicializado e, em 00207 * consequencia disso, os BitMaps dos seus discos ainda nao tinham sido 00208 * carregados. 00209 * @param StorageName nome da maquina com o servidor de armazenamento. 00210 * @return S_OK se nenhum erro ocorreu ao liberar os blocos do arquivo, 00211 * ou diferente de S_OK caso algum erro ocorra ao liberar os blocos do 00212 * arquivo. 00213 */ 00214 int FreeSalvedBlocks( const char *StorageName ); 00215 00216 friend class Disk; 00217 friend class SNode; 00218 }; 00219 00220 00221 /////////////////////////////////////////////////////////////////////////////// 00222 class SNode // storage node 00223 { 00224 public: 00225 static const int sn_maxdisks = MAXSTORAGEDISKSARRAY; 00226 00227 private: 00228 SNode( DiskMgr *mgr, char *hostname ); 00229 ~SNode(); 00230 00231 static void *txthreadep( void *parm ); 00232 int txthread(); 00233 static void *rxthreadep( void *parm ); 00234 int rxthread(); 00235 void rxthread_nodeinfo( EventStorageReply *event ); 00236 void rxthread_diskinfo( EventStorageReply *event ); 00237 /** 00238 * Nova funcao para processar o recebimento da resposta a mensagem de 00239 * inicializacao enviada na funcao DiskMgr::BuildNode. 00240 * @param event ponteiro para evento a ser processado, com a mensagem 00241 * recebida. 00242 */ 00243 void rxthread_confirmation( EventStorageReply *event ); 00244 #ifdef RIO_DEGUG2 00245 /** 00246 * Nova funcao para processar o recebimento da resposta de estado das 00247 * requisicoes de busca. 00248 * Obs: Atualmente esta funcao somente e usada para fins de depuracao 00249 * do codigo. 00250 * @param event ponteiro para evento a ser processado, com a mensagem 00251 * recebida. 00252 */ 00253 void rxthread_searchlogsstatus( EventStorageReply *event ); 00254 #endif 00255 00256 void rxthread_diskservicetimeinfo( EventStorageReply *event ); 00257 // -------------------------------------------------------------------- 00258 00259 SNode *sn_link; 00260 DiskMgr *sn_mgr; 00261 char *sn_hostname; 00262 vsiIPaddress sn_IPaddress; 00263 CvsiTCPsocket sn_socket; 00264 EventQueue sn_sendqueue; 00265 pthread_t sn_txthread; 00266 pthread_t sn_rxthread; 00267 int sn_termflag; 00268 int sn_disks; 00269 int sn_diskidorg; 00270 00271 long long int sn_disksize[sn_maxdisks]; 00272 00273 // Nova flag usada para indicar se estamos reiniciando ou nao o 00274 // servidor de armazenamento. 00275 bool sn_restart; 00276 // Nova flag usada para indicar se o servidor de armazenamento esta 00277 // temporariamente parado (isso ocorrera apois detectarmos que o 00278 // servidor parou ate que a nova conexao seja estabelecida). 00279 bool sn_isenabled; 00280 // Nova variavel usada para definir se devemos ou nao enviar, ao 00281 // Router, o evento EventTypeStorageUp. 00282 bool sn_sendevent; 00283 // Mutex para garantir o acesso exclusivo a variavel sn_isenabled. 00284 pthread_mutex_t sn_mutex; 00285 // Variavel de condicao usada pela funcao de envio quando a conexao 00286 // ainda nao estiver habilitada. 00287 pthread_cond_t sn_waitstorage; 00288 // Variavel booleana usada para indicar se existem blocos pendentes para 00289 // serem liberados (estes blocos serao armazenados no arquivo binario 00290 // com o nome FreeBlocks-sn_hostname. Cada registro deste arquivo sera 00291 // uma estrutura do tipo RioDiskBlock com o bloco a ser liberado). 00292 bool sn_readfreeblocksfile; 00293 00294 friend class DiskMgr; 00295 00296 public: 00297 void SendStorageNode( EventStorageRequest *event, u16 DiskSeq ); 00298 00299 void GetDiskServiceTime( EventStorageRequest* event, u16 DiskSeq ); 00300 // -------------------------------------------------------------------- 00301 }; 00302 00303 /////////////////////////////////////////////////////////////////////////////// 00304 class Disk // an individual disk 00305 { 00306 private: 00307 // only DiskMgr creates these.. 00308 Disk( DiskMgr *mgr, SNode *node ); 00309 ~Disk(); 00310 void SendStorageNode( EventStorageRequest* event ); 00311 int DoIO(); 00312 int GetnBlocks(); 00313 00314 void GetServiceTime( EventStorageRequest* event ); 00315 unsigned int GetNumberOfFreeBlocks(); 00316 int GetName( char *DiskName ); 00317 00318 char d_DiskName[ MaxPathSize ]; // Mudanca para usar um 00319 // caminho com o tamanho 00320 // maximo (este valor ja 00321 // era o maximo, 256, mas 00322 // antes tambem era igual 00323 // a 40). 00324 // -------------------------------------------------------------------- 00325 00326 int d_diskid; // global unique disk id 00327 unsigned int d_ntot; // total blocks 00328 int d_status; 00329 int d_diskseq; // disk seq # on storage node 00330 BitMap d_BitMap; 00331 Disk *d_link; 00332 DiskMgr *d_mgr; 00333 SNode *d_node; 00334 00335 static const int STAT_READ = 0x01; 00336 static const int STAT_WRITE = 0x02; 00337 static const int STAT_ALLOC = 0x04; 00338 00339 friend class DiskMgr; 00340 friend class SNode; 00341 }; 00342