/* * 1 - if request is not submitted since local server can handle it * 0 - if request is submitted successfully * -1 - in case of error submitting request * - out of memory * - invalid arguments * - other system limitations */ int clusterMapGet(clusterMap_t clusterMap, void* luaContext, void* keyContext, char* server, char* key ) { clusterMapImpl_t* pCM = CLUSTER_MAP(clusterMap); request_t* newRequest = 0; externalServer_t* pEServer = 0; int returnValue = 0; IfTrue(pCM && server && key && luaContext, ERR, "Null argument found"); newRequest = createRequest(key, luaContext, keyContext); IfTrue(newRequest, ERR, "Error allocting memory for new request"); pEServer = mapGetElement(pCM->serverMap, server); if (!pEServer) { pEServer = externalServerCreate(server, pCM); IfTrue(pEServer, ERR, "Error creating server entry for server %s", server); mapPutElement(pCM->serverMap, server, pEServer); } externalServerSubmit(pEServer, newRequest); goto OnSuccess; OnError: if (newRequest) { deleteRequest(newRequest); newRequest = 0; } returnValue = -1; OnSuccess: return returnValue; }
void Parse::emit_guard_for_new(ciInstanceKlass* klass) { // Emit guarded new // if (klass->_init_thread != current_thread || // klass->_init_state != being_initialized) // uncommon_trap Node* cur_thread = _gvn.transform( new (C, 1) ThreadLocalNode() ); Node* merge = new (C, 3) RegionNode(3); _gvn.set_type(merge, Type::CONTROL); Node* kls = makecon(TypeKlassPtr::make(klass)); Node* init_thread_offset = _gvn.MakeConX(instanceKlass::init_thread_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset); Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS); Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq); IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); set_control(IfTrue(iff)); merge->set_req(1, IfFalse(iff)); Node* init_state_offset = _gvn.MakeConX(instanceKlass::init_state_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); adr_node = basic_plus_adr(kls, kls, init_state_offset); Node* init_state = make_load(NULL, adr_node, TypeInt::INT, T_INT); Node* being_init = _gvn.intcon(instanceKlass::being_initialized); tst = Bool( CmpI( init_state, being_init), BoolTest::eq); iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); set_control(IfTrue(iff)); merge->set_req(2, IfFalse(iff)); PreserveJVMState pjvms(this); record_for_igvn(merge); set_control(merge); uncommon_trap(Deoptimization::Reason_uninitialized, Deoptimization::Action_reinterpret, klass); }
/* returns -1 on error, 1 if more input is required, 0 when parse is complete */ int responseParserParse(responseParser_t parser, dataStream_t dataStream) { responseParserImpl_t* pParser = RESPONSE_PARSER(parser); char** tokens = 0; int ntokens = 0, endOfLine = 0, parseResult = 0, returnValue = 0; IfTrue(pParser, ERR, "Null Parser Object"); if (pParser->state == parse_first) { endOfLine = dataStreamFindEndOfLine(dataStream); if (endOfLine <= 0) { returnValue = 1; goto OnSuccess; } pParser->endOfLine = endOfLine; tokens = tokenizeFirstLine(pParser->fallocator, dataStream, endOfLine, &ntokens); IfTrue(tokens, DEBUG, "Error getting tokens"); parseResult = parseFirstLineResponse(pParser->fallocator, pParser, tokens, ntokens); if (parseResult < 0) { LOG(INFO, "parsing error %d\n", parseResult); goto OnError; } if (pParser->endOfResponse) { LOG(DEBUG, "endOfResponse %d", pParser->endOfResponse); pParser->endOfValue = endOfLine+2; goto OnSuccess; } pParser->state = parse_data; pParser->endOfValue = endOfLine + 2 + pParser->valueLength + 2; } if (pParser->state == parse_data) { if (dataStreamGetSize(dataStream) < pParser->endOfValue) { returnValue = 1; goto OnSuccess; } pParser->value = dataStreamSubStream(pParser->fallocator, dataStream, (pParser->endOfLine+2), pParser->valueLength); IfTrue(pParser->value, INFO, "Error creating data stream"); } goto OnSuccess; OnError: returnValue = -1; OnSuccess: if (pParser) { cleanupTokens(pParser->fallocator, tokens, ntokens); tokens = 0; } return returnValue; }
/** * creates a request object which encapsulates all the information * necessary for making a request */ static request_t* createRequest(char* virtualKey, void* luaContext, void* keyContext) { request_t* pRequest = ALLOCATE_1(request_t); IfTrue(pRequest, ERR, "Error allocating memory"); pRequest->key = strdup(virtualKey); IfTrue(pRequest->key, ERR, "Error copying key"); pRequest->luaContext = luaContext; pRequest->keyContext = keyContext; goto OnSuccess; OnError: if (pRequest) { deleteRequest(pRequest); pRequest = 0; } OnSuccess: return pRequest; }
/* choosing a default because otherwise everyone has to * choose and ensure that it is same all over, which * could be a pain. * Bigger todo is to have some way to specify weightage * with the servers. */ consistent_t consistentCreate(char* serverNames) { consistentImpl_t* pC = ALLOCATE_1(consistentImpl_t); IfTrue(pC, ERR, "Error allocating memory"); pC->spread = SPREAD; IfTrue( 0 == parseAndSetServerNames(pC, serverNames), ERR, "Error setting server names"); IfTrue( 0 == calculatePoints(pC), ERR, "Error calculating points"); goto OnSuccess; OnError: consistentDelete(pC); pC = 0; OnSuccess: return pC; }
static connectionContext_t* connectionContextCreate(connection_t conn, void* pServer) { connectionContext_t* pContext = ALLOCATE_1(connectionContext_t); IfTrue(conn, ERR, "Null Connection"); IfTrue(pContext, ERR, "Error allocating memory"); pContext->readStream = dataStreamCreate(); IfTrue(pContext->readStream, WARN, "Error creating read stream"); pContext->writeStream = dataStreamCreate(); IfTrue(pContext->writeStream, WARN, "Error creating write stream"); pContext->fallocator = fallocatorCreate(); IfTrue(pContext->fallocator, WARN, "Error creating fallocator"); pContext->parser = responseParserCreate(pContext->fallocator); IfTrue(pContext->parser, WARN, "Error creating parser"); pContext->currentRequests = listCreate(OFFSET(request_t, pNext), OFFSET(request_t, pPrev)); IfTrue(pContext->currentRequests, WARN, "Error creating request list"); pContext->connection = conn; pContext->pExternalServer = pServer; goto OnSuccess; OnError: if (pContext) { connectionContextDelete(pContext, 0); pContext = 0; } OnSuccess: return pContext; }
static externalServer_t* externalServerCreate(char* serverName, clusterMapImpl_t* pCM) { externalServer_t* pServer = ALLOCATE_1(externalServer_t); char* serverNameCopy = 0; char* ip = 0; char* port = 0; IfTrue(pServer, ERR, "Error allocating memory"); pServer->serverName = strdup(serverName); IfTrue(pServer->serverName, ERR, "Error allocating memory"); serverNameCopy = strdup(pServer->serverName); IfTrue(serverNameCopy, ERR, "Error allocating memory"); ip = strtok(serverNameCopy, ":"); IfTrue(ip, ERR, "Error parsing serverName"); pServer->serverIP = strdup(ip); IfTrue(ip, ERR, "Error copying server ip"); port = strtok(0, ":"); IfTrue(port, ERR, "Error parsing server port"); pServer->serverPort = atoi(port); FREE(serverNameCopy); serverNameCopy = 0; pServer->activeConnections = listCreate(OFFSET(connectionContext_t, pNext), OFFSET(connectionContext_t, pPrev)); IfTrue(pServer->activeConnections, ERR, "Error allocating memory"); pServer->freeConnections = listCreate(OFFSET(connectionContext_t, pNext), OFFSET(connectionContext_t, pPrev)); IfTrue(pServer->freeConnections, ERR, "Error allocating memory"); pServer->unassignedRequests = listCreate(OFFSET(request_t, pNext), OFFSET(request_t, pPrev)); IfTrue(pServer->unassignedRequests, ERR, "Error allocating memory"); pServer->pClusterMap = pCM; goto OnSuccess; OnError: if (serverNameCopy) { FREE(serverNameCopy); } if (pServer) { externalServerDelete(pServer); pServer = 0; } OnSuccess: return pServer; }
/** * VALUE key flags datalength\r\n * <DATA>\r\n * END\r\n */ static int parseFirstLineResponse(fallocator_t fallocator, responseParserImpl_t* pParser, char** tokens, int ntokens) { int returnValue = 0; if (0 == strcmp(tokens[0], "END")) { pParser->endOfResponse = 1; goto OnSuccess; } if (0 == strcmp(tokens[0], "VALUE")) { pParser->key = tokens[1]; tokens[1] = 0; IfTrue(safe_strtoul(tokens[2], &pParser->flags), INFO, "Error parsing flags"); IfTrue(safe_strtoul(tokens[3], &pParser->valueLength), INFO, "Error parsing value length"); } goto OnSuccess; OnError: returnValue = -1; OnSuccess: LOG(DEBUG, "endOfResponse %d", pParser->endOfResponse); return returnValue; }
static int calculatePoints(consistentImpl_t* pC) { char key[MAX_SERVER_NAME_SIZE]; int length = 0, returnValue = 0; int requiredSize = pC->spread * pC->serverCount; if (pC->pointsCount != requiredSize) { if (pC->points) { free(pC->points); pC->points = 0; pC->pointsCount = 0; } pC->points = calloc(requiredSize, sizeof(point_t)); IfTrue(pC->points, ERR, "Error allocating memory for points"); pC->pointsCount = requiredSize; } for (int i = 0; i < pC->serverCount; i++) { for (int j = 0; j < pC->spread; j++) { memset(key, 0 , MAX_SERVER_NAME_SIZE); length = snprintf(key, MAX_SERVER_NAME_SIZE, "%s-%d", pC->servers[i].serverName, j); IfTrue(length < MAX_SERVER_NAME_SIZE, ERR, "server names to big"); pC->points[(i*pC->spread)+j].hashPoint = hashcode(pC, key, length); pC->points[(i*pC->spread)+j].serverIndex = i; } } qsort(pC->points, pC->pointsCount, sizeof(point_t), pointsCompare); goto OnSuccess; OnError: if (pC->points) { free(pC->points); pC->points = 0; pC->pointsCount = 0; } returnValue = -1; OnSuccess: return returnValue; }
static int parseAndSetServerNames(consistentImpl_t* pC, char* serverNames) { char* serverNamesCopy = 0; server_t* array = 0; int size = MIN_SERVER_NAMES_SIZE; int count = 0; char* token = 0; int returnValue = 0; IfTrue(pC, ERR, "Null consistent pointer"); IfTrue(serverNames, ERR, "Null server names"); serverNamesCopy = strdup(serverNames); IfTrue(serverNamesCopy, ERR, "Error copying server names"); array = calloc(size, sizeof(char*)); IfTrue(array, ERR, "Error allocating memory"); token = strtok(serverNamesCopy, DELIM); while (token) { array[count].serverName = strdup(token); IfTrue(array[count].serverName, ERR, "Error allocating memory"); array[count].available = 1; count++; if (count == size) { server_t* newArray = realloc(array, sizeof(server_t) * size * 2); IfTrue(newArray, ERR, "Error allocating memory"); array = newArray; size = size * 2; } token = strtok(NULL, DELIM); } freeServers(pC); pC->servers = array; pC->serverCount = count; goto OnSuccess; OnError: if (array) { for (int i = 0; i < count; i++) { if (array[i].serverName) { free(array[i].serverName); array[i].serverName = 0; } } free(array); array = 0; } returnValue = -1; OnSuccess: if (serverNamesCopy) { free(serverNamesCopy); serverNamesCopy = 0; } return returnValue; }
static int externalServerSubmit(externalServer_t* pServer, request_t* pRequest) { int returnValue = 0; connectionContext_t* pCContext = 0; connection_t newConnection = 0; listAddLast(pServer->unassignedRequests, pRequest); pCContext = listRemoveFirst(pServer->freeConnections); if (pCContext) { connectionWaitCancel(pCContext->connection, getGlobalEventBase()); } if (!pCContext) { //check if we have reached max concurrent connections limit // if not, create a new connection if (listGetSize(pServer->activeConnections) < MAX_CONCURRENT_CONNECTIONS) { LOG(DEBUG, "creating new external connection"); newConnection = connectionClientCreate(pServer->serverIP, pServer->serverPort, createConnectionHandler()); IfTrue(newConnection, ERR, "Error creating new connection to %s", pServer->serverName); //got a new connection pCContext = connectionContextCreate(newConnection, pServer); IfTrue(pCContext, ERR, "Error allocting memory for connection context"); connectionSetContext(newConnection, pCContext); newConnection = 0; int err = connectionConnect(pCContext->connection); IfTrue(err >= 0, ERR, "connect failed"); if (err == 1) { LOG(DEBUG, "waiting for connect to complete"); pCContext->status = status_connecting; connectionWaitForConnect(pCContext->connection, getGlobalEventBase()); goto OnSuccess; } }else { //if we have reached max connection limit, we will let the request rest //in the queue. Whenever one of the current connections get free, we will //use that to send the request. returnValue = 1; goto OnSuccess; } } if (pCContext) { pCContext->status = status_active; connectionSubmitRequests(pServer, pCContext); } goto OnSuccess; OnError: if (newConnection) { connectionClose(newConnection); } if (pCContext) { connectionContextDelete(pCContext, 0); } returnValue = 1; OnSuccess: return returnValue; }
static void readAvailableImpl(connection_t connection){ connectionContext_t* pCContext = connectionGetContext(connection); u_int32_t bytesRead = 0; int returnValue = 0; LOG(DEBUG, "got something to read on socket"); //if it is one of the pooled connections if (pCContext->status == status_pooled) { LOG(DEBUG, "socket was pooled..closing on read"); //socket is closed externalServer_t* pServer = pCContext->pExternalServer; listRemove(pServer->freeConnections, pCContext); connectionContextDelete(pCContext, 0); goto OnSuccess; } if (pCContext->status == status_waiting_read) { pCContext->status = status_active; }else { LOG(ERR, "Invalid connection state"); goto OnError; } returnValue = connectionRead(pCContext->connection, pCContext->fallocator, pCContext->readStream, 8 * 1024 , &bytesRead); LOG(DEBUG, "connection read status %d bytesRead %d", returnValue, bytesRead); IfTrue(returnValue >= 0, INFO, "Socket closed"); doParseMore: returnValue = responseParserParse(pCContext->parser, pCContext->readStream); LOG(DEBUG, "response parser status %d", returnValue); IfTrue(returnValue >= 0, INFO, "Parsing Error %d", returnValue); if (returnValue == 1) { LOG(DEBUG, "need to wait for read"); pCContext->status = status_waiting_read; connectionWaitForRead(pCContext->connection, getGlobalEventBase()); goto OnSuccess; } char* key = 0; dataStream_t value = 0; u_int32_t flags = 0; returnValue = responseParserGetResponse(pCContext->parser, pCContext->readStream, &key, &value, &flags); LOG(DEBUG, "got resposonse %d key %s", returnValue, key); if (returnValue == 0) { externalServer_t* pServer = pCContext->pExternalServer; clusterMapImpl_t* pCM = pServer->pClusterMap; request_t* pRequest = 0; tryNext: pRequest = listRemoveFirst(pCContext->currentRequests); if (pRequest) { if (0 == strcmp(pRequest->key, key)) { //we got the response for the key LOG(DEBUG, "giving callback for success result"); pCM->resultHandler(pRequest->luaContext, pRequest->keyContext, 0, value); dataStreamDelete(value); value = 0; fallocatorFree(pCContext->fallocator, key); key = 0; deleteRequest(pRequest); pRequest = 0; goto doParseMore; }else { //this key is different from the key we expected //the request for current key failed, so notify LOG(DEBUG, "giving callback for fail result"); pCM->resultHandler(pRequest->luaContext, pRequest->keyContext, -1, NULL); deleteRequest(pRequest); pRequest = 0; //move on to the next key, may be its her response goto tryNext; } }else { // no more request in the currentRequests list? // what this means is that we got a response for a key // which we didn't asked for... // that is strange.., some server issue..we can't do much dataStreamDelete(value); value = 0; fallocatorFree(pCContext->fallocator, key); key = 0; // now so just close this connection externalServer_t* pServer = pCContext->pExternalServer; listRemove(pServer->activeConnections, pCContext); connectionContextDelete(pCContext, 0); pCContext = 0; } }else { LOG(DEBUG, "end of results from response parser"); // we go END response from parser externalServer_t* pServer = pCContext->pExternalServer; clusterMapImpl_t* pCM = pServer->pClusterMap; request_t* pRequest = 0; //anything pending in the currentRequests..not found while ((pRequest = listRemoveLast(pCContext->currentRequests)) != 0) { //report error pCM->resultHandler(pRequest->luaContext, pRequest->keyContext, -1, NULL); deleteRequest(pRequest); } // add this connections to free connections list listRemove(pServer->activeConnections, pCContext); connectionSubmitRequests(pServer, pCContext); } goto OnSuccess; OnError: if (pCContext) { externalServer_t* pServer = pCContext->pExternalServer; listRemove(pServer->activeConnections, pCContext); connectionContextDelete(pCContext, 1); pCContext = 0; } OnSuccess: return; }
static int parseFirstLineRequest(fallocator_t fallocator, requestParserImpl_t* pParser, char** tokens, int ntokens) { int returnValue = 0; if (ntokens >= 2 && (((strcmp(tokens[0], "get") == 0) && (pParser->pCommand->command = COMMAND_GET)) || ((strcmp(tokens[0], "bget") == 0) && (pParser->pCommand->command = COMMAND_BGET)))) { if (ntokens > 2) { //copy the keys ... pParser->pCommand->multiGetKeys = fallocatorMalloc(fallocator, (ntokens-1) * sizeof(char*)); IfTrue(pParser->pCommand->multiGetKeys, WARN, "Error allocating memory"); pParser->pCommand->multiGetKeysCount = ntokens -1 ; for (int i = 1; i < ntokens; i++) { pParser->pCommand->multiGetKeys[i-1] = tokens[i]; tokens[i] = 0; } }else { pParser->pCommand->key = tokens[1]; pParser->pCommand->keySize = strlen(tokens[1]); tokens[1] = 0; } } else if ((ntokens == 5 || ntokens == 6) && ((strcmp(tokens[0], "add") == 0 && (pParser->pCommand->command = COMMAND_ADD)) || (strcmp(tokens[0], "set") == 0 && (pParser->pCommand->command = COMMAND_SET)) || (strcmp( tokens[0], "replace") == 0 && (pParser->pCommand->command = COMMAND_REPLACE)) || (strcmp(tokens[0], "prepend") == 0 && (pParser->pCommand->command = COMMAND_PREPEND)) || (strcmp(tokens[0], "append") == 0 && (pParser->pCommand->command = COMMAND_APPEND)))) { pParser->pCommand->key = tokens[1]; pParser->pCommand->keySize = strlen(tokens[1]); tokens[1] = 0; IfTrue(safe_strtoul(tokens[2], &pParser->pCommand->flags), INFO, "Error parsing flags"); IfTrue(safe_strtoul(tokens[3], &pParser->pCommand->expiryTime), INFO, "Error parsing expiry time "); IfTrue(safe_strtoul(tokens[4], &pParser->pCommand->dataLength), INFO, "Error parsing data length"); if (tokens[5] != NULL) { if (strcmp(tokens[5], "noreply") == 0) { pParser->pCommand->noreply = 1; } } } else if ((ntokens == 6 || ntokens == 7) && (strcmp(tokens[0], "cas") == 0)) { pParser->pCommand->command = COMMAND_CAS; pParser->pCommand->key = tokens[1]; pParser->pCommand->keySize = strlen(tokens[1]); tokens[1] = 0; IfTrue(safe_strtoul(tokens[2], &pParser->pCommand->flags), INFO, "Error parsing flags"); IfTrue(safe_strtoul(tokens[3], &pParser->pCommand->expiryTime), INFO, "Error parsing expiry time "); IfTrue(safe_strtoul(tokens[4], &pParser->pCommand->dataLength), INFO, "Error parsing data length"); IfTrue(safe_strtoull(tokens[5], &pParser->pCommand->cas), INFO, "Error parsing cas id"); if (tokens[6] != NULL) { if (strcmp(tokens[6], "noreply") == 0) { pParser->pCommand->noreply = 1; } } } else if ((ntokens == 3 || ntokens == 4) && (strcmp(tokens[0], "incr") == 0)) { pParser->pCommand->command = COMMAND_INCR; pParser->pCommand->key = tokens[1]; pParser->pCommand->keySize = strlen(tokens[1]); tokens[1] = 0; IfTrue(safe_strtoull(tokens[2], &pParser->pCommand->delta), INFO, "Error parsing delta"); if (tokens[3] != NULL) { if (strcmp(tokens[3], "noreply") == 0) { pParser->pCommand->noreply = 1; } } } else if (ntokens >= 2 && (strcmp(tokens[0], "gets") == 0)) { pParser->pCommand->command = COMMAND_GETS; pParser->pCommand->key = tokens[1]; pParser->pCommand->keySize = strlen(tokens[1]); tokens[1] = 0; //TODO - only suport one key per get for now } else if ((ntokens == 4 || ntokens == 5) && (strcmp(tokens[0], "decr") == 0)) { pParser->pCommand->command = COMMAND_DECR; pParser->pCommand->key = tokens[1]; pParser->pCommand->keySize = strlen(tokens[1]); tokens[1] = 0; IfTrue(safe_strtoull(tokens[2], &pParser->pCommand->delta), INFO, "Error parsing delta"); if (tokens[3] != NULL) { if (strcmp(tokens[3], "noreply") == 0) { pParser->pCommand->noreply = 1; } } } else if (ntokens >= 2 && ntokens <= 4 && (strcmp(tokens[0], "delete") == 0)) { pParser->pCommand->command = COMMAND_DELETE; pParser->pCommand->key = tokens[1]; pParser->pCommand->keySize = strlen(tokens[1]); tokens[1] = 0; if (tokens[2] != NULL) { if (strcmp(tokens[2], "noreply") == 0) { pParser->pCommand->noreply = 1; } } } else if (ntokens >= 2 && (strcmp(tokens[0], "stats") == 0)) { pParser->pCommand->command = COMMAND_STATS; //TODO - later } else if (ntokens >= 1 && ntokens <= 2 && (strcmp(tokens[0], "flush_all") == 0)) { pParser->pCommand->command = COMMAND_FLUSH_ALL; //TODO - later } else if (ntokens == 1 && (strcmp(tokens[0], "version") == 0)) { pParser->pCommand->command = COMMAND_VERSION; //TODO - later } else if (ntokens == 1 && (strcmp(tokens[0], "quit") == 0)) { pParser->pCommand->command = COMMAND_QUIT; //TODO - later } else if ((ntokens == 2 || ntokens == 3) && (strcmp(tokens[0], "verbosity") == 0)) { pParser->pCommand->command = COMMAND_VERBOSITY; IfTrue(safe_strtoul(tokens[2], &pParser->pCommand->flags), INFO, "Error parsing verosity level"); } else { //this is error } goto OnSuccess; OnError: returnValue = -1; OnSuccess: return returnValue; }