@@ -1852,152 +1852,6 @@ void dbsync_payload_load (sqlite3_context *context, int argc, sqlite3_value **ar
18521852}
18531853#endif
18541854
1855- // MARK: - Download spool -
1856-
1857- // Abandoned download streams (a client that started a chunked /check drain and
1858- // never finished) are reaped after this many seconds. Matches the v3 fragment
1859- // stale window.
1860- #define CLOUDSYNC_PAYLOAD_SPOOL_STALE_SECONDS (24*60*60)
1861-
1862- // cloudsync_payload_spool_fill(stream_id, since_db_version, filter_site_id, exclude)
1863- // Generate the whole chunk stream for a window once into cloudsync_payload_spool
1864- // so the /check path can page it out one chunk per call. Returns the number of
1865- // chunks spooled for stream_id. Idempotent: a prior complete fill is kept as-is.
1866- static void dbsync_payload_spool_fill (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
1867- DEBUG_FUNCTION ("cloudsync_payload_spool_fill" );
1868- UNUSED_PARAMETER (argc );
1869-
1870- sqlite3 * db = sqlite3_context_db_handle (context );
1871- if (sqlite3_value_type (argv [0 ]) == SQLITE_NULL ) {
1872- sqlite3_result_error (context , "cloudsync_payload_spool_fill: stream_id is required." , -1 );
1873- return ;
1874- }
1875- const char * stream_id = (const char * )sqlite3_value_text (argv [0 ]);
1876- int stream_id_len = sqlite3_value_bytes (argv [0 ]);
1877- int64_t since = sqlite3_value_int64 (argv [1 ]);
1878- bool site_given = (sqlite3_value_type (argv [2 ]) != SQLITE_NULL );
1879- int exclude = (sqlite3_value_int (argv [3 ]) != 0 );
1880-
1881- sqlite3_stmt * stmt = NULL ;
1882- int rc = sqlite3_exec (db , SQL_PAYLOAD_SPOOL_CREATE_TABLE , NULL , NULL , NULL );
1883- if (rc != SQLITE_OK ) goto error ;
1884-
1885- // Stale-GC of abandoned streams (coarse-grained, no throttle needed).
1886- if (sqlite3_prepare_v2 (db , SQL_PAYLOAD_SPOOL_CLEANUP_STALE , -1 , & stmt , NULL ) == SQLITE_OK ) {
1887- sqlite3_bind_int64 (stmt , 1 , (int64_t )time (NULL ) - CLOUDSYNC_PAYLOAD_SPOOL_STALE_SECONDS );
1888- sqlite3_step (stmt );
1889- }
1890- sqlite3_finalize (stmt ); stmt = NULL ;
1891-
1892- // Atomic fill: a partial/failed generation must never persist, so that the
1893- // idempotency check below ("rows present == complete stream") holds.
1894- rc = sqlite3_exec (db , "SAVEPOINT cloudsync_spool_fill;" , NULL , NULL , NULL );
1895- if (rc != SQLITE_OK ) goto error ;
1896-
1897- int64_t count = 0 ;
1898- rc = sqlite3_prepare_v2 (db , SQL_PAYLOAD_SPOOL_COUNT , -1 , & stmt , NULL );
1899- if (rc != SQLITE_OK ) goto rollback ;
1900- sqlite3_bind_text (stmt , 1 , stream_id , stream_id_len , SQLITE_TRANSIENT );
1901- if (sqlite3_step (stmt ) == SQLITE_ROW ) count = sqlite3_column_int64 (stmt , 0 );
1902- sqlite3_finalize (stmt ); stmt = NULL ;
1903-
1904- if (count == 0 ) {
1905- rc = sqlite3_prepare_v2 (db , SQL_PAYLOAD_SPOOL_FILL_INSERT , -1 , & stmt , NULL );
1906- if (rc != SQLITE_OK ) goto rollback ;
1907- sqlite3_bind_text (stmt , 1 , stream_id , stream_id_len , SQLITE_TRANSIENT );
1908- sqlite3_bind_int64 (stmt , 2 , since );
1909- if (site_given ) sqlite3_bind_blob (stmt , 3 , sqlite3_value_blob (argv [2 ]), sqlite3_value_bytes (argv [2 ]), SQLITE_TRANSIENT );
1910- else sqlite3_bind_null (stmt , 3 );
1911- sqlite3_bind_int (stmt , 4 , exclude );
1912- rc = sqlite3_step (stmt );
1913- sqlite3_finalize (stmt ); stmt = NULL ;
1914- if (rc != SQLITE_DONE ) goto rollback ;
1915-
1916- rc = sqlite3_prepare_v2 (db , SQL_PAYLOAD_SPOOL_MARK_FINAL , -1 , & stmt , NULL );
1917- if (rc != SQLITE_OK ) goto rollback ;
1918- sqlite3_bind_text (stmt , 1 , stream_id , stream_id_len , SQLITE_TRANSIENT );
1919- rc = sqlite3_step (stmt );
1920- sqlite3_finalize (stmt ); stmt = NULL ;
1921- if (rc != SQLITE_DONE ) goto rollback ;
1922-
1923- rc = sqlite3_prepare_v2 (db , SQL_PAYLOAD_SPOOL_COUNT , -1 , & stmt , NULL );
1924- if (rc != SQLITE_OK ) goto rollback ;
1925- sqlite3_bind_text (stmt , 1 , stream_id , stream_id_len , SQLITE_TRANSIENT );
1926- if (sqlite3_step (stmt ) == SQLITE_ROW ) count = sqlite3_column_int64 (stmt , 0 );
1927- sqlite3_finalize (stmt ); stmt = NULL ;
1928- }
1929-
1930- sqlite3_exec (db , "RELEASE cloudsync_spool_fill;" , NULL , NULL , NULL );
1931- sqlite3_result_int64 (context , count );
1932- return ;
1933-
1934- rollback :
1935- sqlite3_finalize (stmt );
1936- sqlite3_result_error (context , sqlite3_errmsg (db ), -1 );
1937- sqlite3_result_error_code (context , rc );
1938- sqlite3_exec (db , "ROLLBACK TO cloudsync_spool_fill; RELEASE cloudsync_spool_fill;" , NULL , NULL , NULL );
1939- return ;
1940-
1941- error :
1942- sqlite3_result_error (context , sqlite3_errmsg (db ), -1 );
1943- sqlite3_result_error_code (context , rc );
1944- }
1945-
1946- // cloudsync_payload_spool_drop(stream_id) -> number of chunks removed.
1947- // Called once a stream has been fully delivered/acked (or to force-evict).
1948- static void dbsync_payload_spool_drop (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
1949- DEBUG_FUNCTION ("cloudsync_payload_spool_drop" );
1950- UNUSED_PARAMETER (argc );
1951-
1952- sqlite3 * db = sqlite3_context_db_handle (context );
1953- if (sqlite3_value_type (argv [0 ]) == SQLITE_NULL ) {
1954- sqlite3_result_error (context , "cloudsync_payload_spool_drop: stream_id is required." , -1 );
1955- return ;
1956- }
1957-
1958- int rc = sqlite3_exec (db , SQL_PAYLOAD_SPOOL_CREATE_TABLE , NULL , NULL , NULL );
1959- if (rc != SQLITE_OK ) { sqlite3_result_error (context , sqlite3_errmsg (db ), -1 ); return ; }
1960-
1961- sqlite3_stmt * stmt = NULL ;
1962- rc = sqlite3_prepare_v2 (db , SQL_PAYLOAD_SPOOL_DELETE , -1 , & stmt , NULL );
1963- if (rc != SQLITE_OK ) { sqlite3_result_error (context , sqlite3_errmsg (db ), -1 ); return ; }
1964- sqlite3_bind_text (stmt , 1 , (const char * )sqlite3_value_text (argv [0 ]), sqlite3_value_bytes (argv [0 ]), SQLITE_TRANSIENT );
1965- rc = sqlite3_step (stmt );
1966- sqlite3_finalize (stmt );
1967- if (rc != SQLITE_DONE ) { sqlite3_result_error (context , sqlite3_errmsg (db ), -1 ); return ; }
1968- sqlite3_result_int64 (context , sqlite3_changes (db ));
1969- }
1970-
1971- // cloudsync_payload_spool_drop_chunk(stream_id, chunk_index) -> number of chunks removed.
1972- // Called after one S3-backed chunk has been safely persisted outside the spool.
1973- static void dbsync_payload_spool_drop_chunk (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
1974- DEBUG_FUNCTION ("cloudsync_payload_spool_drop_chunk" );
1975- UNUSED_PARAMETER (argc );
1976-
1977- sqlite3 * db = sqlite3_context_db_handle (context );
1978- if (sqlite3_value_type (argv [0 ]) == SQLITE_NULL ) {
1979- sqlite3_result_error (context , "cloudsync_payload_spool_drop_chunk: stream_id is required." , -1 );
1980- return ;
1981- }
1982- if (sqlite3_value_type (argv [1 ]) == SQLITE_NULL ) {
1983- sqlite3_result_error (context , "cloudsync_payload_spool_drop_chunk: chunk_index is required." , -1 );
1984- return ;
1985- }
1986-
1987- int rc = sqlite3_exec (db , SQL_PAYLOAD_SPOOL_CREATE_TABLE , NULL , NULL , NULL );
1988- if (rc != SQLITE_OK ) { sqlite3_result_error (context , sqlite3_errmsg (db ), -1 ); return ; }
1989-
1990- sqlite3_stmt * stmt = NULL ;
1991- rc = sqlite3_prepare_v2 (db , SQL_PAYLOAD_SPOOL_DELETE_CHUNK , -1 , & stmt , NULL );
1992- if (rc != SQLITE_OK ) { sqlite3_result_error (context , sqlite3_errmsg (db ), -1 ); return ; }
1993- sqlite3_bind_text (stmt , 1 , (const char * )sqlite3_value_text (argv [0 ]), sqlite3_value_bytes (argv [0 ]), SQLITE_TRANSIENT );
1994- sqlite3_bind_int64 (stmt , 2 , sqlite3_value_int64 (argv [1 ]));
1995- rc = sqlite3_step (stmt );
1996- sqlite3_finalize (stmt );
1997- if (rc != SQLITE_DONE ) { sqlite3_result_error (context , sqlite3_errmsg (db ), -1 ); return ; }
1998- sqlite3_result_int64 (context , sqlite3_changes (db ));
1999- }
2000-
20011855// MARK: - Register -
20021856
20031857int dbsync_register_with_flags (sqlite3 * db , const char * name , void (* xfunc )(sqlite3_context * ,int ,sqlite3_value * * ), void (* xstep )(sqlite3_context * ,int ,sqlite3_value * * ), void (* xfinal )(sqlite3_context * ), int nargs , int flags , char * * pzErrMsg , void * ctx , void (* ctx_free )(void * )) {
@@ -2319,14 +2173,6 @@ int dbsync_register_functions (sqlite3 *db, char **pzErrMsg) {
23192173 rc = dbsync_register_function (db , "cloudsync_payload_blob_checked" , dbsync_payload_blob_checked , 5 , pzErrMsg , ctx , NULL );
23202174 if (rc != SQLITE_OK ) return rc ;
23212175
2322- // Download spool (server-side /check chunk staging)
2323- rc = dbsync_register_function (db , "cloudsync_payload_spool_fill" , dbsync_payload_spool_fill , 4 , pzErrMsg , ctx , NULL );
2324- if (rc != SQLITE_OK ) return rc ;
2325- rc = dbsync_register_function (db , "cloudsync_payload_spool_drop" , dbsync_payload_spool_drop , 1 , pzErrMsg , ctx , NULL );
2326- if (rc != SQLITE_OK ) return rc ;
2327- rc = dbsync_register_function (db , "cloudsync_payload_spool_drop_chunk" , dbsync_payload_spool_drop_chunk , 2 , pzErrMsg , ctx , NULL );
2328- if (rc != SQLITE_OK ) return rc ;
2329-
23302176 #ifdef CLOUDSYNC_DESKTOP_OS
23312177 rc = dbsync_register_function (db , "cloudsync_payload_save" , dbsync_payload_save , 1 , pzErrMsg , ctx , NULL );
23322178 if (rc != SQLITE_OK ) return rc ;
0 commit comments