1+ - header checksum always checked
2+ - no . of records always less than last pos
3+ - optional to write and check page checksum
4+ - record length should not exceed remaining page size
5+ - column length should not exceed remaining record size
16/*
27 Sqlite Micro Logger
38
3439#define LEN_OF_HDR_LEN 2
3540#define CHKSUM_LEN 3
3641
42+ enum {ULS_ST_NOT_FINAL = 0xA4 , ULS_ST_WRITE_PENDING ,
43+ ULS_ST_WRITING_IDX , ULS_ST_FINAL };
44+
3745// Returns how many bytes the given integer will
3846// occupy if stored as a variable integer
3947int8_t get_vlen_of_uint16 (uint16_t vint ) {
@@ -687,7 +695,7 @@ int uls_append_row_with_values(struct uls_write_context *wctx,
687695 write_uint16 (ptr + 3 , rec_count );
688696 write_uint16 (ptr + 5 , last_pos );
689697 write_uint16 (ptr + 8 - 2 + (rec_count * 2 ), last_pos );
690- wctx -> flush_flag = 0xA5 ;
698+ wctx -> state = ULS_ST_WRITE_PENDING ;
691699
692700 return ULS_RES_OK ;
693701}
@@ -711,7 +719,7 @@ int uls_append_empty_row(struct uls_write_context *wctx) {
711719 write_uint16 (ptr + 3 , rec_count );
712720 write_uint16 (ptr + 5 , last_pos );
713721 write_uint16 (ptr + 8 - 2 + (rec_count * 2 ), last_pos );
714- wctx -> flush_flag = 0xA5 ;
722+ wctx -> state = ULS_ST_WRITE_PENDING ;
715723
716724 return ULS_RES_OK ;
717725}
@@ -788,7 +796,7 @@ int uls_set_col_val(struct uls_write_context *wctx,
788796 write_uint16 (ptr + 5 , new_last_pos );
789797 rec_count -- ;
790798 write_uint16 (ptr + 8 + rec_count * 2 , new_last_pos );
791- wctx -> flush_flag = 0xA5 ;
799+ wctx -> state = ULS_ST_WRITE_PENDING ;
792800
793801 return ULS_RES_OK ;
794802}
@@ -810,28 +818,42 @@ int uls_flush(struct uls_write_context *wctx) {
810818 return res ;
811819 int ret = wctx -> flush_fn (wctx );
812820 if (!ret )
813- wctx -> flush_flag = 0 ;
821+ wctx -> state = ULS_ST_NOT_FINAL ;
814822 return ret ;
815823}
816824
817825// See .h file for API description
818826int uls_partial_finalize (struct uls_write_context * wctx ) {
819827 int32_t page_size = get_pagesize (wctx -> page_size_exp );
820- if (wctx -> flush_flag == 0xA5 ) {
828+ if (wctx -> state == ULS_ST_WRITE_PENDING ) {
821829 uls_flush (wctx );
822- wctx -> flush_flag = 0xA5 ;
830+ wctx -> state = ULS_ST_WRITE_PENDING ;
823831 }
824832 int res = read_bytes_wctx (wctx , wctx -> buf , 0 , page_size );
825833 if (res )
826834 return res ;
827835 if (memcmp (wctx -> buf , sqlite_sig , 16 ) == 0 )
828836 return ULS_RES_OK ;
829- // There was a flush just now, so update the last page in first page
830- if (wctx -> flush_flag == 0xA5 ) {
831- write_uint32 (wctx -> buf + 60 , wctx -> cur_write_page );
832- res = write_page (wctx , 0 , page_size );
833- if (res )
834- return res ;
837+ uint32_t last_leaf_page = read_uint32 (wctx -> buf + 60 );
838+ // Update the last page no. in first page
839+ if (last_leaf_page == 0 ) {
840+ if (!wctx -> cur_write_page ) {
841+ byte head_buf [8 ];
842+ do {
843+ res = read_bytes_wctx (wctx , head_buf , (wctx -> cur_write_page + 1 ) * page_size , 8 );
844+ if (res )
845+ break ;
846+ if (head_buf [0 ] == 13 )
847+ wctx -> cur_write_page ++ ;
848+ } while (head_buf [0 ] == 13 );
849+ }
850+ if (wctx -> cur_write_page ) {
851+ write_uint32 (wctx -> buf + 60 , wctx -> cur_write_page );
852+ res = write_page (wctx , 0 , page_size );
853+ if (res )
854+ return res ;
855+ } else
856+ return ULS_RES_MALFORMED ;
835857 }
836858 return ULS_RES_OK ;
837859}
@@ -902,6 +924,31 @@ int uls_not_finalized(struct uls_write_context *wctx) {
902924 return ULS_RES_NOT_FINALIZED ;
903925}
904926
927+ int32_t uls_read_page_size (struct uls_write_context * wctx ) {
928+ int res = read_bytes_wctx (wctx , wctx -> buf , 0 , 72 );
929+ if (res )
930+ return res ;
931+ if (check_signature (wctx -> buf ))
932+ return ULS_RES_INVALID_SIG ;
933+ int32_t page_size = read_uint16 (wctx -> buf + 16 );
934+ wctx -> page_size_exp = get_page_size_exp (page_size );
935+ if (!wctx -> page_size_exp )
936+ return ULS_RES_INVALID_SIG ;
937+ if (page_size == 1 )
938+ return 65536 ;
939+ return page_size ;
940+ }
941+
942+ // See .h file for API description
943+ int uls_recover (struct uls_write_context * wctx ) {
944+ wctx -> state = ULS_ST_NOT_FINAL ;
945+ wctx -> cur_write_page = 0 ;
946+ int res = uls_finalize (wctx );
947+ if (res )
948+ return res ;
949+ return ULS_RES_OK ;
950+ }
951+
905952// See .h file for API description
906953int uls_init_for_append (struct uls_write_context * wctx ) {
907954 int res = read_bytes_wctx (wctx , wctx -> buf , 0 , 72 );
@@ -918,7 +965,6 @@ int uls_init_for_append(struct uls_write_context *wctx) {
918965 res = read_bytes_wctx (wctx , wctx -> buf , 0 , page_size );
919966 if (res )
920967 return res ;
921- wctx -> flush_flag = 0 ;
922968 wctx -> cur_write_page = read_uint32 (wctx -> buf + 60 );
923969 if (wctx -> cur_write_page == 0 )
924970 return ULS_RES_NOT_FINALIZED ;
@@ -933,9 +979,7 @@ int uls_init_for_append(struct uls_write_context *wctx) {
933979 res = read_bytes_wctx (wctx , wctx -> buf , wctx -> cur_write_page * page_size , page_size );
934980 if (res )
935981 return res ;
936- res = uls_append_empty_row (wctx );
937- if (res )
938- return res ;
982+ wctx -> state = ULS_ST_NOT_FINAL ;
939983 return ULS_RES_OK ;
940984}
941985
0 commit comments