// TODO add copyright #include #include #include #include #include #include #include #include #include #include // #define _S3_DEVEL_ 1 #ifdef _S3_DEVEL_ #include #endif #include "constants.h" #include "s3_local.h" #include "s3_access.h" #ifndef SLEEP_UNITS_PER_SECOND #define SLEEP_UNITS_PER_SECOND 1 #endif using std::ios; S3Access *S3Access::instance_; const std::string S3Access::access_key = "LRDC5AOZ75ZVW4J9DIY7"; const std::string S3Access::host = "svllabsg01-g1.eng.netapp.com:8082"; const std::string S3Access::bucket_name = "Bucket2"; const std::string S3Access::secret_key = "3nMbpA83GfL65jLPr712UMaH4c7/g+XHtQXyOlGx"; const S3Protocol S3Access::protocolG = S3ProtocolHTTPS; const S3UriStyle S3Access::uriStyleG = S3UriStylePath; S3Access::S3Access() :header_printed(false), retriesG(5), statusG(S3StatusOK) { bucketContext.hostName = host.c_str(); // bucketContext.hostName = 0; bucketContext.bucketName = bucket_name.c_str(); bucketContext.protocol = S3ProtocolHTTPS; bucketContext.uriStyle = S3UriStylePath; bucketContext.accessKeyId = access_key.c_str(); bucketContext.secretAccessKey = secret_key.c_str(); responseHandler.propertiesCallback = &responsePropertiesCallback; responseHandler.completeCallback = &responseCompleteCallback; listServiceHandler.responseHandler = responseHandler, listServiceHandler.listServiceCallback = &listServiceCallback; listBucketHandler.responseHandler = responseHandler; listBucketHandler.listBucketCallback = &listBucketCallback; putObjectHandler.responseHandler = responseHandler; putObjectHandler.putObjectDataCallback = &putObjectDataCallback; deleteResponseHandler.propertiesCallback = 0; deleteResponseHandler.completeCallback = &responseCompleteCallback; getObjectHandler.responseHandler = responseHandler; getObjectHandler.getObjectDataCallback = &getObjectDataCallback; } S3Status S3Access::responsePropertiesCallback( const S3ResponseProperties *properties, void *callbackData) { S3ResponseProperties *response_properties = static_cast(callbackData); if (NULL == properties) { std::cout<<"In S3Access::responsePropertiesCallback, properties returned is NULL"<contentType = properties->contentType; response_properties->contentLength = properties->contentLength; response_properties->server = properties->server; response_properties->lastModified = properties->lastModified; } return S3StatusOK; } uint64_t S3Access::convertInt(const char *str, const char *paramName) { uint64_t ret = 0; while (*str) { if (!isdigit(*str)) { fprintf(stderr, "\nERROR: Nondigit in %s parameter: %c\n", paramName, *str); } ret *= 10; ret += (*str++ - '0'); } return ret; } void S3Access::responseCompleteCallback( S3Status status, const S3ErrorDetails *error, void *callbackData) { return; } int S3Access::should_retry() { if (retriesG--) { // Sleep before next retry; start out with a 1 second sleep /*static int retrySleepInterval = 1 * SLEEP_UNITS_PER_SECOND; sleep(retrySleepInterval); // Next sleep 1 second longer retrySleepInterval++;*/ return 1; } return 0; } void S3Access::printListServiceHeader(int allDetails) { printf("%-56s %-20s", " Bucket", " Created"); if (allDetails) { printf(" %-64s %-12s", " Owner ID", "Display Name"); } printf("\n"); printf("-------------------------------------------------------- " "--------------------"); if (allDetails) { printf(" -------------------------------------------------" "--------------- ------------"); } printf("\n"); } S3Status S3Access::listServiceCallback( const char *ownerId, const char *ownerDisplayName, const char *bucketName, int64_t creationDate, void *callbackData) { list_service_data *data = (list_service_data *) callbackData; if (!data->headerPrinted) { data->headerPrinted = 1; printListServiceHeader(data->allDetails); } char timebuf[256]; if (creationDate >= 0) { time_t t = (time_t) creationDate; strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); } else { timebuf[0] = 0; } printf("%-56s %-20s", bucketName, timebuf); if (data->allDetails) { printf(" %-64s %-12s", ownerId ? ownerId : "", ownerDisplayName ? ownerDisplayName : ""); } printf("\n"); return S3StatusOK; } S3Status S3Access::listBucketCallback( int isTruncated, const char *nextMarker, int contentsCount, const S3ListBucketContent *contents, int commonPrefixesCount, const char **commonPrefixes, void *callbackData) { std::vector *list_of_objects = static_cast *>(callbackData); for (int i = 0; i < contentsCount; i++) { char timebuf[256]; const S3ListBucketContent *content = &(contents[i]); (*list_of_objects).push_back(content->key); } return S3StatusOK; } void S3Access::printError() { if (statusG < S3StatusErrorAccessDenied) { fprintf(stderr, "\nERROR: %s\n", S3_get_status_name(statusG)); } else { fprintf(stderr, "\nERROR: %s\n", S3_get_status_name(statusG)); fprintf(stderr, "%s\n", errorDetailsG); } } void S3Access::resetRetryCount() { retriesG = 5; } void S3Access::list_all_buckets(int allDetails) { list_service_data data; data.headerPrinted = 0; data.allDetails = allDetails; resetRetryCount(); do { S3_list_service(protocolG, access_key.c_str(), secret_key.c_str(), 0, 0, &listServiceHandler, &data); } while (S3_status_is_retryable(statusG) && should_retry()); if (statusG == S3StatusOK) { if (!data.headerPrinted) { printListServiceHeader(allDetails); } } else { printError(); } //deinitialize(); } int S3Access::putObjectDataCallback(int bufferSize, char *buffer, void *callbackData) { put_object_callback_data *put_cb_data = (put_object_callback_data *) callbackData; int lenToRead =(put_cb_data->pendingContentLength >bufferSize) ? bufferSize :put_cb_data->pendingContentLength; int64_t offset = put_cb_data->totalContentLength - put_cb_data->pendingContentLength; memcpy((void *)buffer, (void *)&put_cb_data->buff[offset], lenToRead); put_cb_data->pendingContentLength -= lenToRead; return lenToRead; } S3Status S3Access::getObjectDataCallback(int bufferSize, const char *buffer, void *callbackData) { get_object_callback_data *object_data = (get_object_callback_data *)(callbackData); printf ("s3access::getobjectdatacallback: length, buffersize=%u=============buffer=\n \n", bufferSize); int i; char *bp; uint8_t by; for (i=0, bp=(char *)buffer; itotalContentLength = bufferSize; memcpy(object_data->buff, buffer, bufferSize); //*data = std::string(buffer, bufferSize); } void S3Access::initialize() { S3Status status; //const char *hostname = getenv("S3_HOSTNAME"); if ((status = S3_initialize("s3", S3_INIT_ALL, host.c_str())) != S3StatusOK) { fprintf(stderr, "Failed to initialize libs3: %s\n", S3_get_status_name(status)); exit(-1); } } void S3Access::printListBucketHeader(int allDetails) { printf("%-50s %-20s %-5s", " Key", " Last Modified", "Size"); if (allDetails) { printf(" %-34s %-64s %-12s", " ETag", " Owner ID", "Display Name"); } printf("\n"); printf("-------------------------------------------------- " "-------------------- -----"); if (allDetails) { printf(" ---------------------------------- " "-------------------------------------------------" "--------------- ------------"); } printf("\n"); } void S3Access::list_bucket(const char *bucketName, const char *prefix, const char *marker, const char *delimiter, int maxkeys, int allDetails) { S3BucketContext bucketContext = { 0, bucketName, protocolG, uriStyleG, access_key.c_str(), secret_key.c_str() }; list_bucket_callback_data data; snprintf(data.nextMarker, sizeof(data.nextMarker), "%s", marker); data.keyCount = 0; data.allDetails = allDetails; resetRetryCount(); do { std::cout << "Times \n"; data.isTruncated = 0; do { S3_list_bucket(&bucketContext, prefix, data.nextMarker, delimiter, maxkeys, 0, &listBucketHandler, &data); } while (S3_status_is_retryable(statusG) && should_retry()); if (statusG != S3StatusOK) { break; } } while (data.isTruncated && (!maxkeys || (data.keyCount < maxkeys))); if (statusG == S3StatusOK) { if (!data.keyCount) { //printListBucketHeader(allDetails); } } else { printError(); } } void S3Access::deinitialize() { S3_deinitialize(); } std::string S3Access::put_object(std::string key, uint64_t contentLength, char *data, void *response_func) { const char *cacheControl = 0, *contentType = 0, *md5 = 0; const char *contentDispositionFilename = 0, *contentEncoding = 0; int64_t expires = -1; S3CannedAcl cannedAcl = S3CannedAclPrivate; int metaPropertiesCount = 0; S3NameValue metaProperties[S3_MAX_METADATA_COUNT]; char useServerSideEncryption = 0; S3PutProperties putProperties; putProperties.contentType = contentType; putProperties.md5 = md5; putProperties.cacheControl = cacheControl; putProperties.contentDispositionFilename = contentDispositionFilename; putProperties.contentEncoding = contentEncoding; putProperties.expires = expires; putProperties.cannedAcl = cannedAcl; putProperties.metaDataCount = metaPropertiesCount; putProperties.metaData = metaProperties; putProperties.useServerSideEncryption = useServerSideEncryption; put_object_callback_data put_cb_data; put_cb_data.buff = data; put_cb_data.totalContentLength = contentLength; put_cb_data.pendingContentLength = contentLength; S3_put_object(&bucketContext, key.c_str(), contentLength, &putProperties, 0, &putObjectHandler, &put_cb_data); return "Success"; } std::string S3Access::put_object_range(std::string key, uint64_t offset, uint64_t contentLength, char *data, void *response_func) { const char *cacheControl = 0, *contentType = 0, *md5 = 0; const char *contentDispositionFilename = 0, *contentEncoding = 0; int64_t expires = -1; S3CannedAcl cannedAcl = S3CannedAclPrivate; int metaPropertiesCount = 0; S3NameValue metaProperties[S3_MAX_METADATA_COUNT]; char useServerSideEncryption = 0; S3PutProperties putProperties; putProperties.contentType = contentType; putProperties.md5 = md5; putProperties.cacheControl = cacheControl; putProperties.contentDispositionFilename = contentDispositionFilename; putProperties.contentEncoding = contentEncoding; putProperties.expires = expires; putProperties.cannedAcl = cannedAcl; putProperties.metaDataCount = metaPropertiesCount; putProperties.metaData = metaProperties; putProperties.useServerSideEncryption = useServerSideEncryption; put_object_callback_data put_cb_data; put_cb_data.buff = data; put_cb_data.totalContentLength = contentLength; put_cb_data.pendingContentLength = contentLength; S3_put_object_range(&bucketContext, key.c_str(), contentLength, offset, &putProperties, 0, &putObjectHandler, &put_cb_data); return "Success"; } int S3Access::get_object(std::string key, char * object_buffer, uint64_t *size) { int ret = 0; int64_t ifModifiedSince = -1, ifNotModifiedSince = -1; const char *ifMatch = 0, *ifNotMatch = 0; S3GetConditions getConditions; getConditions.ifModifiedSince = ifModifiedSince; getConditions.ifNotModifiedSince = ifNotModifiedSince; getConditions.ifMatchETag = ifMatch; getConditions.ifNotMatchETag = ifNotMatch; get_object_callback_data object_data; object_data.buff = object_buffer; if(NULL == object_buffer) { return -1; } resetRetryCount(); do { S3_get_object(&bucketContext, key.c_str(), &getConditions, 0, 0, NULL, &getObjectHandler, &object_data); std::cout<<"Waiting in .........get_object"< S3Access::list_bucket_objects(std::string prefix) { std::vector list_of_objects; std::cout<<"Inside S3Access::list_bucket_objects"<