static void _start_thread(SG_context * pCtx, void* pFunc, void* pParam, pthread_t* pThreadId)
// pCtx: input parameter only (used for logging)
{
	pthread_t	thread_id;
//	pthread_attr_t	attr;
	int		retval;

//	(void) pthread_attr_init(&attr);
//	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	retval = pthread_create(&thread_id, NULL, pFunc, pParam);
	if (retval)
		SG_ERR_THROW2_RETURN(SG_ERR_ERRNO(retval), 
			(pCtx, "%s", "pthread_create failed"));

	*pThreadId = thread_id;
}
예제 #2
0
void SG_time__get_milliseconds_since_1970_utc(SG_context* pCtx, SG_int64* pResult)
{
	struct timeval tv;
	SG_int64 result;
	int rc;

	rc = gettimeofday(&tv, NULL);
	if (rc)
	{
		*pResult = 0;
		SG_ERR_THROW_RETURN( SG_ERR_ERRNO(errno) );
	}

	result = (SG_int64) tv.tv_sec;
	result *= MILLISECONDS_PER_SECOND;
	result += (tv.tv_usec / 1000);
	*pResult = result;

}
static void send_upload_request(
    SG_context* pCtx,
    CFHTTPMessageRef myRequest,
    CFReadStreamRef upload,
    CFReadStreamRef* pp
)
{
    CFReadStreamRef myReadStream = NULL;

    myReadStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, myRequest, upload);

    if (!CFReadStreamOpen(myReadStream))
    {
        CFStreamError myErr = CFReadStreamGetError(myReadStream);

        if (myErr.domain == kCFStreamErrorDomainPOSIX)
        {
            // Interpret myErr.error as a UNIX errno.
            SG_ERR_THROW(  SG_ERR_ERRNO(myErr.error)  );
        }
        else if (myErr.domain == kCFStreamErrorDomainMacOSStatus)
        {
            // Interpret myErr.error as a MacOS error code.
            // TODO SG_ERR_THROW(  SG_ERR_MAC((OSStatus) myErr.error)  );
            SG_ERR_THROW(  SG_ERR_UNSPECIFIED  );
        }
    }

    *pp = myReadStream;
    myReadStream = NULL;

fail:
    if (myReadStream)
    {
        CFReadStreamClose(myReadStream);
        CFRelease(myReadStream);
        myReadStream = NULL;
    }
}
void u0038_test_name_conflict(SG_context * pCtx)
{
	thread_data* pThreadData = NULL;
	SG_closet_descriptor_handle* ph = NULL;
	SG_vhash* pvh = NULL;
	SG_closet_descriptor_handle* ph2 = NULL;
	SG_vhash* pvh2 = NULL;
#if defined(WINDOWS)
	HANDLE hThread = NULL;
#else
	pthread_t thread_id = 0;
#endif

	SG_ERR_IGNORE(  SG_closet__descriptors__remove(pCtx, "1")  );
	SG_ERR_IGNORE(  SG_closet__descriptors__remove(pCtx, "2")  );

	VERIFY_ERR_CHECK(  SG_closet__descriptors__add_begin(pCtx, "1", NULL, NULL, NULL, NULL, &pvh, &ph)  );

	VERIFY_ERR_CHECK(  SG_alloc1(pCtx, pThreadData)  );
	VERIFY_ERR_CHECK(  SG_context__alloc__temporary(&pThreadData->pCtx)  );
#if defined(WINDOWS)
	VERIFY_ERR_CHECK(  _start_thread(pCtx, _add_conflicting_descriptor_in_thread, pThreadData, &hThread)  );
#else
	VERIFY_ERR_CHECK(  _start_thread(pCtx, _add_conflicting_descriptor_in_thread, pThreadData, &thread_id)  );
#endif

	VERIFY_ERR_CHECK(  SG_sleep_ms(1000)  );
	VERIFY_ERR_CHECK(  SG_closet__descriptors__add_commit(pCtx, &ph, pvh, SG_REPO_STATUS__NORMAL)  );
	VERIFY_COND("", !ph);
	SG_VHASH_NULLFREE(pCtx, pvh);

#if defined(WINDOWS)
	{
		DWORD dwRet = WaitForSingleObject(hThread, 1000);
		VERIFY_COND("failure waiting for thread termination", dwRet == WAIT_OBJECT_0);
		VERIFY_CTX_IS_OK("thread context has error", pThreadData->pCtx);
		(void) CloseHandle(hThread);
	}
#else
	{
		int rc = pthread_join(thread_id, NULL);
		if (rc)
			SG_ERR_THROW2(SG_ERR_ERRNO(rc), (pCtx, "%s", "pthread_join failed"));
		VERIFY_CTX_IS_OK("thread context has error", pThreadData->pCtx);
	}
#endif

	VERIFY_ERR_CHECK(  SG_closet__descriptors__add_begin(pCtx, "2", NULL, NULL, NULL, NULL, &pvh2, &ph2)  );
	VERIFY_ERR_CHECK(  SG_closet__descriptors__add_commit(pCtx, &ph2, pvh2, SG_REPO_STATUS__NORMAL)  );
	
	VERIFY_ERR_CHECK_ERR_EQUALS_DISCARD(SG_closet__descriptors__add_begin(pCtx, "1", NULL, NULL, NULL, NULL, &pvh, &ph),
		SG_ERR_REPO_ALREADY_EXISTS);
	VERIFY_COND("", !pvh);
	VERIFY_COND("", !ph);

	/* fall through */
fail:
	SG_VHASH_NULLFREE(pCtx, pvh);
	SG_VHASH_NULLFREE(pCtx, pvh2);
	SG_ERR_IGNORE(SG_closet__descriptors__add_abort(pCtx, &ph));
	SG_ERR_IGNORE(SG_closet__descriptors__add_abort(pCtx, &ph2));
	if (pThreadData)
	{
		SG_CONTEXT_NULLFREE(pThreadData->pCtx);
		SG_NULLFREE(pCtx, pThreadData);
	}
	SG_ERR_IGNORE(  SG_closet__descriptors__remove(pCtx, "1")  );
	SG_ERR_IGNORE(  SG_closet__descriptors__remove(pCtx, "2")  );
}
static void perform_upload_request__string(
    SG_context* pCtx,
    CFHTTPMessageRef myRequest,
    SG_pathname* pPath,
    CFHTTPMessageRef* pmyResponse,
    SG_string** ppstr
)
{
    CFReadStreamRef myReadStream = NULL;
    CFHTTPMessageRef myResponse = NULL;
    SG_string* pstr = NULL;
    CFReadStreamRef upload = NULL;
    CFURLRef upload_file_url = NULL;

    // set the content-length header
    {
        SG_uint64 len = 0;
        SG_ERR_CHECK(  SG_fsobj__length__pathname(pCtx, pPath, &len, NULL)  );

        CFStringRef headerFieldName = CFSTR("Content-Length");
        CFStringRef headerFieldValue = CFStringCreateWithFormat (kCFAllocatorDefault, NULL,  CFSTR("%d"), len);
        CFHTTPMessageSetHeaderFieldValue(myRequest, headerFieldName, headerFieldValue);
        CFRelease(headerFieldValue);
    }

    upload_file_url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*) SG_pathname__sz(pPath), SG_STRLEN(SG_pathname__sz(pPath)), SG_FALSE);
    upload = CFReadStreamCreateWithFile(kCFAllocatorDefault, upload_file_url);
    CFRelease(upload_file_url);
    if (!CFReadStreamOpen(upload))
    {
        CFStreamError myErr = CFReadStreamGetError(upload);

        if (myErr.domain == kCFStreamErrorDomainPOSIX)
        {
            // Interpret myErr.error as a UNIX errno.
            SG_ERR_THROW(  SG_ERR_ERRNO(myErr.error)  );
        }
        else if (myErr.domain == kCFStreamErrorDomainMacOSStatus)
        {
            // Interpret myErr.error as a MacOS error code.
            // TODO SG_ERR_THROW(  SG_ERR_MAC((OSStatus) myErr.error)  );
            SG_ERR_THROW(  SG_ERR_UNSPECIFIED  );
        }
    }

    SG_ERR_CHECK(  send_upload_request(pCtx, myRequest, upload, &myReadStream)  );
    SG_ERR_CHECK(  read_entire_stream__string(pCtx, myReadStream, &pstr, &myResponse)  );

    *ppstr = pstr;
    pstr = NULL;

    *pmyResponse = myResponse;
    myResponse = NULL;

fail:
    if (upload)
    {
        CFRelease(upload);
    }
    if (myReadStream)
    {
        CFReadStreamClose(myReadStream);
        CFRelease(myReadStream);
        myReadStream = NULL;
    }

    if (myResponse)
    {
        CFRelease(myResponse);
        myResponse = NULL;
    }

    SG_STRING_NULLFREE(pCtx, pstr);
}
static void read_entire_stream__string(
    SG_context* pCtx,
    CFReadStreamRef myReadStream,
    SG_string** ppstr,
    CFHTTPMessageRef* pp
)
{
    SG_string* pstr = NULL;
    CFHTTPMessageRef myResponse = NULL;
    CFIndex numBytesRead = 0;

    SG_ERR_CHECK(  SG_string__alloc__sz(pCtx, &pstr, "")  );
    do
    {
        UInt8 buf[8192]; // TODO
        numBytesRead = CFReadStreamRead(myReadStream, buf, sizeof(buf));
        if( numBytesRead > 0 )
        {
            SG_ERR_CHECK(  SG_string__append__buf_len(pCtx, pstr, buf, numBytesRead)  );

            if (!myResponse)
            {
                myResponse = (CFHTTPMessageRef)CFReadStreamCopyProperty(myReadStream, kCFStreamPropertyHTTPResponseHeader);
            }
        }
        else if( numBytesRead < 0 )
        {
            CFStreamError myErr = CFReadStreamGetError(myReadStream);
            // TODO clean this up
            if (myErr.domain == kCFStreamErrorDomainPOSIX)
            {
                if (ETIMEDOUT == myErr.error)
                {
                    usleep(5000);
                    numBytesRead = 0;
                }
                else
                {
                    // Interpret myErr.error as a UNIX errno.
                    SG_ERR_THROW(  SG_ERR_ERRNO(myErr.error)  );
                }
            }
            else if (myErr.domain == kCFStreamErrorDomainMacOSStatus)
            {
                // Interpret myErr.error as a MacOS error code.
                // TODO SG_ERR_THROW(  SG_ERR_MAC((OSStatus) myErr.error)  );
                SG_ERR_THROW(  SG_ERR_UNSPECIFIED  );
            }
        }
    } while( numBytesRead > 0 );

    if (!myResponse)
    {
        myResponse = (CFHTTPMessageRef)CFReadStreamCopyProperty(myReadStream, kCFStreamPropertyHTTPResponseHeader);
    }

    *pp = myResponse;
    myResponse = NULL;

    *ppstr = pstr;
    pstr = NULL;

fail:
    if (myResponse)
    {
        CFRelease(myResponse);
    }
    SG_STRING_NULLFREE(pCtx, pstr);
}
static void read_entire_stream__file(
    SG_context* pCtx,
    CFReadStreamRef myReadStream,
    SG_pathname* pPath,
    CFHTTPMessageRef* pp,
    SG_bool b_progress
)
{
    CFHTTPMessageRef myResponse = NULL;
    CFIndex numBytesRead = 0;
    SG_file* pFile = NULL;
    SG_int64 content_length = 0;
    SG_int64 so_far = 0;

    SG_ERR_CHECK(  SG_file__open__pathname(pCtx, pPath, SG_FILE_CREATE_NEW | SG_FILE_WRONLY, 0644, &pFile)  );
    do
    {
        UInt8 buf[8192]; // TODO
        numBytesRead = CFReadStreamRead(myReadStream, buf, sizeof(buf));
        if( numBytesRead > 0 )
        {
            SG_ERR_CHECK(  SG_file__write(pCtx, pFile, numBytesRead, buf, NULL)  );
            if (!myResponse)
            {
                myResponse = (CFHTTPMessageRef)CFReadStreamCopyProperty(myReadStream, kCFStreamPropertyHTTPResponseHeader);
                CFStringRef contentLengthString = CFHTTPMessageCopyHeaderFieldValue(myResponse, CFSTR("Content-Length"));
                if (contentLengthString)
                {
                    // TODO 32 bit limit problem here
                    content_length = CFStringGetIntValue(contentLengthString);
                    CFRelease(contentLengthString);
                }
                if (b_progress)
                {
                    SG_ERR_CHECK(  SG_log__set_steps(pCtx, content_length / 1024, "KB")  );
                }
            }
            so_far += (SG_uint32) numBytesRead;
            if (b_progress)
            {
                SG_ERR_CHECK(  SG_log__set_finished(pCtx, so_far / 1024)  );
            }
        }
        else if( numBytesRead < 0 )
        {
            CFStreamError myErr = CFReadStreamGetError(myReadStream);
            // TODO clean this up
            if (myErr.domain == kCFStreamErrorDomainPOSIX)
            {
                if (ETIMEDOUT == myErr.error)
                {
                    usleep(5000);
                    numBytesRead = 0;
                }
                else
                {
                    // Interpret myErr.error as a UNIX errno.
                    SG_ERR_THROW(  SG_ERR_ERRNO(myErr.error)  );
                }
            }
            else if (myErr.domain == kCFStreamErrorDomainMacOSStatus)
            {
                // Interpret myErr.error as a MacOS error code.
                // TODO SG_ERR_THROW(  SG_ERR_MAC((OSStatus) myErr.error)  );
                SG_ERR_THROW(  SG_ERR_UNSPECIFIED  );
            }
        }
    } while( numBytesRead > 0 );

    SG_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );

    if (!myResponse)
    {
        myResponse = (CFHTTPMessageRef)CFReadStreamCopyProperty(myReadStream, kCFStreamPropertyHTTPResponseHeader);
    }

    *pp = myResponse;
    myResponse = NULL;

fail:
    if (pFile)
    {
        SG_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );
        // TODO delete it too
    }
    if (myResponse)
    {
        CFRelease(myResponse);
    }
}